Autor Tema: Problemas encontrados con el compilador de CCS  (Leído 13279 veces)

0 Usuarios y 2 Visitantes están viendo este tema.

Desconectado pocher

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 2568
Problemas encontrados con el compilador de CCS
« en: 05 de Abril de 2008, 04:07:21 »
Abro este hilo porque por culpa de un mal funcionamiento (bajo mi punto de vista) del compilador he perdido varias horas.

Creo que para que esto no le sucediera a nadie más, deberíamos poner aquí en este Tema todos los problemas-errores que creamos que tiene el compilador, los discutiríamos entre todos y si efectivamente se trata de un error del compilador alguno de los moderadores pasaría a limpio un resumen del problema y lo incluiríamos en un Tema con chincheta arriba de todo para que estuviera bien visible y que por estos errores nadie más perdiese más tiempo.

Os paso a detallar lo que me ha pasado. El PROBLEMA está en la interrupción por cambio de estado en portB RB4..RB7, resulta que el compilador al salir de la interrupción baja la bandera RBIF pero no hace una lectura/escritura en el portB y estas dos cosas se deben cumplir (mirar el Datasheet) para que de nuevo no entre en la interrupción hasta que realmente haya otro cambio de estado. Si no se hace una lectura/escritura en el portB el programa se vuelve loco y está contínuamente entrando y saliendo de la interrupción.

La SOLUCION es leer/escribir el portB antes de abandonar la interrupción mediante un input ó un output de relleno, ó mejor aún para no perder tiempo hacerlo en ensamblador como bien dice jfh900 mediante las sentencias: #asm movf port_b,0 #endasm

Programa de ejemplo en el que sucede esto:

Código: [Seleccionar]
#include <16F876a.h>
#fuses NOWDT,XT, NOPUT, NOPROTECT
#use delay(clock=4000000)

#byte port_b=6

#INT_RB
Interrupcion_RB()
{
delay_ms(20);     //Antirebotes
  //#asm movf port_b,0 #endasm //Sin quitamos esta instrucción de relleno no funciona bien la interrupción
output_toggle(PIN_a0);
}

void main()
{
set_tris_a(0x00);      // Todo salidas
  set_tris_b(0xFF);    // Todo entradas
  output_a(0x00);

  enable_interrupts(INT_RB);
  enable_interrupts(GLOBAL);

  while(true);
}

Os animo a que comenteis este PROBLEMA y también a que si habeis detectado más problemas del compilador que los pegueis en este Tema para ser comentados.

Un saludo






Desconectado vszener

  • Moderador Local
  • PIC24H
  • *****
  • Mensajes: 2395
Re: Problemas encontrados con el compilador de CCS
« Respuesta #1 en: 05 de Abril de 2008, 04:35:48 »
Yo en su día también pensé que era un error del compilador, pero creo que no lo es, el CCS sigue fiel, en este aspecto, al datasheet, que pone que el flag RBIF se debe 'limpiar' por software.

Al igual que si programamos en ASM el MPSAM no limpia este registro, sino que es tarea del programador de ponerlo a '0', el CCS hace igual, deja la tarea al programador.

En su día me acuerdo que tube una charla sobre este caso mismo con el amigo jfh900 en el post de Ejemplitos...

Aunque pienso igual que tu, que ya que se debe hacer pues que lo haga el compilador por sí mismo y nos ahorre tareas.


Suerte!!! ;)
· Nos vemos en los bares!!!!!
· Mi Blog: Aqueronte

Desconectado pocher

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 2568
Re: Problemas encontrados con el compilador de CCS
« Respuesta #2 en: 05 de Abril de 2008, 06:06:06 »
Si miras el fichero.lst verás como el compilador sí limpia por software el flag 0 del registro INTCON (RBIF) (Hace un BCF 0B.0) pero por lo que parece no hay una lectura/escritura del portb con lo que la interrupción vuelve a dispararse.

Desconectado migsantiago

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8257
    • Sitio de MigSantiago
Re: Problemas encontrados con el compilador de CCS
« Respuesta #3 en: 05 de Abril de 2008, 11:41:58 »
Hola

CCS trae un ejemplo del uso de esa interrupción... EX_PBUTT.C. Me imagino que haciéndolo como ese no debe haber problema.

En su manejo de la interrupción hacen esto:

Código: [Seleccionar]
#int_rb
void detect_rb_change() {
   int current;
   static int last=0;

   set_tris_b(0xF0);
   current=input_b();

   #if LOWTOHIGH
   if ((!bit_test(last,4))&&(bit_test(current,4))) {dbutton4=1;}
   if ((!bit_test(last,5))&&(bit_test(current,5))) {dbutton5=1;}
   if ((!bit_test(last,6))&&(bit_test(current,6))) {dbutton6=1;}
   if ((!bit_test(last,7))&&(bit_test(current,7))) {dbutton7=1;}
   #elif HIGHTOLOW
   if ((!bit_test(current,4))&&(bit_test(last,4))) {dbutton4=1;}
   if ((!bit_test(current,5))&&(bit_test(last,5))) {dbutton5=1;}
   if ((!bit_test(current,6))&&(bit_test(last,6))) {dbutton6=1;}
   if ((!bit_test(current,7))&&(bit_test(last,7))) {dbutton7=1;}
   #endif

   last=current;
}

Desconectado jfh900

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3595
Re: Problemas encontrados con el compilador de CCS
« Respuesta #4 en: 05 de Abril de 2008, 11:47:03 »
Efectivamente este fue un problema que a mi personalmente me llevo muchas horas, aunque después leyendo el datasheet del micro entendí cual era el problema. La verdad es que la solución es muy fácil y al final trabaja correctamente.

Un saludo
* Cuando hables, procura que tus palabras sean mejores que el silencio.
* 'Todos somos ignorantes, lo que ocurre es que no todos ignoramos las mismas cosas.' Albert Einstein.
* No hay nada peor que un experto para evitar el progreso en un campo
* "La vida es como una novela. No importa que sea larga, sino que esté bien narrada" Seneca
* La vida no se vive por las veces que respiras, sino por los momentos que dejan sin aliento.
* Dios dijo: ∇·E=ρ/ε0 ; ∇·B=0 ; ∇xE=-dB/dt ; ∇xB= μ0ε0dE/dt..y la luz se hizo..!!..

Desde España Jesús

Desconectado pocher

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 2568
Re: Problemas encontrados con el compilador de CCS
« Respuesta #5 en: 05 de Abril de 2008, 14:15:41 »
migsantiago ese ejemplo seguro que funciona bien ya que se efectua dentro de la interrupción una lectura del portb mediante current=input_b();

jfh900 al final se resuelve pero las horas perdidas hasta que al final ves el problema no te las devuelve nadie. El problema se resuelve, como bien sabes, haciendo una lectura/escritura del portb dentro de la interrupción, pero esto creo que lo tenían que haber hecho los de CCS, no nosotros.

¿Qué os parece, metemos esto como un olvido del compilador y le ponemos una chincheta para que la gente lo vea y nadie más se vuelva "tarumba" (majareta) con esto?

Desconectado jfh900

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3595
Re: Problemas encontrados con el compilador de CCS
« Respuesta #6 en: 05 de Abril de 2008, 14:26:35 »
A mi me parece bien.

Un saludo
* Cuando hables, procura que tus palabras sean mejores que el silencio.
* 'Todos somos ignorantes, lo que ocurre es que no todos ignoramos las mismas cosas.' Albert Einstein.
* No hay nada peor que un experto para evitar el progreso en un campo
* "La vida es como una novela. No importa que sea larga, sino que esté bien narrada" Seneca
* La vida no se vive por las veces que respiras, sino por los momentos que dejan sin aliento.
* Dios dijo: ∇·E=ρ/ε0 ; ∇·B=0 ; ∇xE=-dB/dt ; ∇xB= μ0ε0dE/dt..y la luz se hizo..!!..

Desde España Jesús

Desconectado migsantiago

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8257
    • Sitio de MigSantiago
Re: Problemas encontrados con el compilador de CCS
« Respuesta #7 en: 05 de Abril de 2008, 14:52:25 »
Chincheta obligatoria.  :idea:

Pero hay que editar el título del tema a: "Problema con Interrupción RB4-7" o algo así.

Desconectado pocher

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 2568
Re: Problemas encontrados con el compilador de CCS
« Respuesta #8 en: 05 de Abril de 2008, 16:30:49 »
Oido cocina, mañana que es domingo, no puedo, pero el lunes le pongo una chincheta.

La idea que yo tengo es poner aquí en este tema un determinado "bug" de CCS (de cualquier cosa), discutirlo entre todos y si se llega a la conclusión que efectivamente es un "bug" hacer una buena explicación y copiarlo en limpio en el tema con chincheta. El título del Tema con chincheta podría ser "Posibles bugs del compilador de CCS" si os parece bien.

Antes de seguir con esta cruzada he de decir que para mí el compilador de C que más me gusta es el de CCS, no porque sea el mejor, que quizá no lo sea, sino por la gran cantidad de personas que lo usan y que en un momento dado te pueden ayudar a resolver una duda.

Esta tarde se vé que tengo ganas de fastidiar al compilador y creo que he descubierto otra cosa que no funciona bien. Ojala me equivoque, por eso lo pongo aquí para discutirlo.

Se trata de la prioridad de las interrupciones en los PIC18.

Si un PIC18 tengo 2 interrupciones y una de ellas la declaro como de alta prioridad, pués si cuando se está ejecutando la instrucción de baja prioridad, llega la de alta prioridad pués 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 creo que esto no funciona.

Os pongo un programa de ejemplo y os digo como reacciona.

Código: [Seleccionar]
#include <18F452.h>

#DEVICE HIGH_INTS=true

#use delay(clock=4000000)

#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                     
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                     
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(0xF5); // 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_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 y a continuación activamos la de RB4..RB7 tendría que ejecutar primero la interrupción RB4..RB7 y activar la salida RB3 para luego regresar a la interrupción RB0 y activar la salida RA0. Pués no, hace justamente lo contrario, primero activa la salida RA0 y luego la salida RB3.

Aquí os lo dejo, pensarlo.
« Última modificación: 07 de Abril de 2008, 13:42:59 por pocher »

Desconectado gu1llermo

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 217
Re: Problemas encontrados con el compilador de CCS
« Respuesta #9 en: 05 de Abril de 2008, 17:38:14 »
Hola pocher, la idea de bugs del compilador CCS me parece buena, porque a mi también me ha pasado que pienso que es un error del CCS (y lo más probable es que así sea  :wink: 8)) jejeje mentira, es mío y es un error por desconocimiento, por ejemplo para el caso de leer el puerto B en una interrupción por cambio de estado del RB7:RB4 desde asembler vengo leyendo el puerto B al ocurrir y además desactivar el flag de interrupción, como ya hemos visto todo así lo indica el datasheet, el porqué el compialador del CCS no incluye esta lectura del puerto B, es porque supongo que si entramos allí tenemos que leerlo para saber si fue un flanco ascendente o descendente, por lo que al salir ya hemos hecho la lectura y el compilar se encarga de borrar la bandera de dicha interrupción, el ejemplo que colgó migsantiago está demasiado bueno  8)

Por otro lado, no e trabajado todavía con las priroridades de las interrupciones pero creo ver porque entra 1ero en la interrupción del RB0 antes de la de RB7:RB4, prueba esto

Agrega un clear_interrupt()

Código: [Seleccionar]
...
enable_interrupts(GLOBAL);
enable_interrupts(INT_RB);
clear_interrupt(INT_EXT);// Para evitar posible interrupción indeseada antes de tiempo
enable_interrupts(INT_EXT);
...

Igual cuando habilites una interrupción de timers es bueno hacer un clear_interrupt y así evitar interrupciones prematuras.

Otra cosa, no veo que habilites el flanco en el que quiere que entre por la interrupción de RB0, utilizando la instrucción: ext_int_edge() yo por lo general lo defino, para saber cuando ocurre y porque no sé cuál es la que hace por defecto, tendría que ver el datasheet.

Para terminar, decir que la idea me gusta, porque como bien dices a veces tardamos mucho tiempo tratando de resolver algo y lo primero que pensamos es que el compilador no sirve  8) me pasó también hace poco tratando de pasar una estructura por referencia a una función, en éste subforo se puede encontrar la solución que me han dado.

Saludos.
« Última modificación: 05 de Abril de 2008, 17:46:46 por gu1llermo »

Desconectado Cryn

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4169
Re: Problemas encontrados con el compilador de CCS
« Respuesta #10 en: 06 de Abril de 2008, 00:24:49 »
interesantes observaciones. tambien sucedio algo similar conmigo, pero con el rs232, en realidad conla interrupcion rda:

Código: [Seleccionar]
#int_rda
void isr_rda()
{
output_toggle(pin_a1);
...
}

si no se coloca un c=getc(); por algun lado, de preferencia al inicio
igual se queda colgado en la interrupcion
.

Desconectado pocher

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 2568
Re: Problemas encontrados con el compilador de CCS
« Respuesta #11 en: 06 de Abril de 2008, 02:13:16 »
Hola Guillermo.

El entrar en la interrupción RB4..RB7 no necesariamente a de ser para leer el portB, puedes leer el portA, incrementar un contador, activar un flag, tomarte una caña ...  ¡a no! esto último no.  :D

El añadir clear_interrupt(INT_EXT); lo único que hace es borrar el flag INTF inicialmente (comprobado). Lo que tendría que hacer el programa es que si activamos la entrada RB0 y a continuación p.e. la entrada RB7 pués debería abandonar la interrupción de RB0 inmediatamente y hacer la de RB4..RB7, pero no lo hace.

Si no se incluye ext_int_edge() hace por omisión el flanco ascendente (en el tratamiento de prioridades de interrupciones que estamos haciendo esto sería indiferente).

Hola Cryn.

Conforme lo tienes debería de ir bien sin necesidad de c=get(c) . En este tipo de interrupción RDA he entrado en ocasiones solo para para activar un flag y salir y no es necesario el get(c). Convendría que especificaras concretamente el programa donde te pasó.

PD. El tratamiento de las prioridades lo estoy haciendo sobre simulador. El lunes si puedo lo pruebo físicamente.




Desconectado gu1llermo

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 217
Re: Problemas encontrados con el compilador de CCS
« Respuesta #12 en: 06 de Abril de 2008, 11:23:29 »
Ah! ok, ya te entiendo un poco mejor pocher, y una pregunta: cómo te das cuenta de que no deja la interrupción RB0 para atender la RB7? estás simulando en el Mplab? por otro lado, para que esto sucediera, me refiero a que deje de atender la interrupción RB0 para atender la RB7 sería habilitando el bit GIE al entrar en cualquier otra rutina de manejo de interrupción excepto en la de RB7, pero el problema de esto es que si estamos en la interrupción del timer0 (por ejemplo) y ocurre una interrupción del timer1, entonces dejará de atender la interrupción del timer0 para atender la del timer1, y si ocurren muchas interrupciones al mismo tiempo puede ocurrir un overflow del stack del pic y alli si que nos volvemos un 8  :?.

Por eso de estar dentro de un interrupción para dejarla, la única forma que veo es habilitando el bit GIE, el problema: cualquier otra interrupción aprovechará esa condición para entrar, a menos que estemos utilizando solo dos interrupciones  y solo habilitamos dicho bit dentro del manejo de la interrupción de menor prioridad :idea: allí si me imagino que podríamos hacer eso  :wink:

PD: Acabo de leer que estás haciendo las pruebas en el simulador, porque probarlo en físico no sé como hacerlo, todo corre muy rápido  :shock: 8) en cambio en el simulador le doy step by step  ;-)

Saludos.

Desconectado Cryn

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4169
Re: Problemas encontrados con el compilador de CCS
« Respuesta #13 en: 07 de Abril de 2008, 00:55:50 »
Conforme lo tienes debería de ir bien sin necesidad de c=get(c) . En este tipo de interrupción RDA he entrado en ocasiones solo para para activar un flag y salir y no es necesario el get(c). Convendría que especificaras concretamente el programa donde te pasó.

bueno dejame buscar el código de ser necesario, porque lo hice como te mencione, sin el getc() y no me salia de la interrupcion, eso lo vi depurando en el proteus, se quedaba colgado ahí
aumente el getc() y recien salia de la interrupcion, de veras :mrgreen:
.

Desconectado pocher

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 2568
Re: Problemas encontrados con el compilador de CCS
« Respuesta #14 en: 07 de Abril de 2008, 13:40:10 »
Ah! ok, ya te entiendo un poco mejor pocher, y una pregunta: cómo te das cuenta de que no deja la interrupción RB0 para atender la RB7?

Me doy cuenta viendo las salidas:

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 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.

Todo esto lo hice con el simulador, ahora recien acabo de probarlo físicamente con un 18F4550 y también va mal (la prioridad se la pasa por el forro).

Me he metido en el buscador del FORO y he estado largo rato leyendo mensajes sobre prioridades en las interrupciones, pero en todos los que he leido y han sido unos cuantos nadie se queja de que el compilador lo esté haciendo mal (programas que tengan prioridad de interrupciones no he visto ninguno). Que raro, ¿no se le ha presentado este problema a nadie? ... a ver si estoy "pa lla" (ido, grillao, zombi, aguilipollao).