Autor Tema: Un macro me resetea el PIC?  (Leído 2332 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado rodogodo

  • PIC10
  • *
  • Mensajes: 5
Un macro me resetea el PIC?
« en: 04 de Enero de 2007, 16:29:53 »
Hola Amigos, Estoy haciendo un programa con un PIC16F877A. El mismo emplea interrupciones para atender los comandos recibidos desde una PC empleando USART. A estos comandos responde rápidamente salvo en dos de ellos, los cuales provocan un cálculo un poco mas complejo en el pic; esos cálculos los resuelvo empleando unas macros que cree. Ahora bien, me ocurre que si envío cualquier comando simple, el programa funciona bien. Pero al enviar cualquiera de los complicados, se resetea. Lo curioso es que no ocurre siempre!!!  :shock: Siempre contesta el PIC, dándome la pauta de que ejecuta completamente la rutina que atiende la interrupción, pero a veces, con esos comandos, se resetea. Probé eliminar las macros en esos comandos, y no se reseteó más! Obviamente, no anda del todo,... pero al menos "sobrevive". No se que mas controlar, las macros parecen andar bien, las probé en programas más cortos de prueba. Si las necesitan, las mando.  Que hago????

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Re: Un macro me resetea el PIC?
« Respuesta #1 en: 04 de Enero de 2007, 16:44:25 »
Si la interrupción tarda mucho en ejecutarse, quizás sea buena idea hacer que levante un flag y procesar ese comando en el bucle principal de tu programa.

De todas formas, es muy aventurado anticipar un posible diagnóstico sin ver tu programa. Lo suyo sería que lo pegaras por aquí.

Desconectado maunix

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 4751
    • Mi Sitio Web Personal
Re: Un macro me resetea el PIC?
« Respuesta #2 en: 04 de Enero de 2007, 17:22:07 »
rodogodo sin ver tu código te puedo sugerir algunas cosas

a) Fíjate que guardes bien los registros Wreg, Pclath y el status al ingresar al vector de interrupción.  Esto se llama "context saving" o grabado del contexto y sirve para que cuando tu pic salga de la rutina de interrupción vuelva al mismo y preciso lugar de donde fue llamado.  Si tu programa vuelve a otro lugar, es probable que caiga en alguna región de programa alta y ejecute todas las instrucciones allí guardadas (típicamente es todos unos es decir 0x3FF con lo cual el pic ejecutará un nop).  Una vez que termina de ejecutar la última línea de código en la última posición del programa, regresará a 0x000 por overflow del Program Counter

b) Revisa que no estes anidando más de 8 calls.  Si esto ocurre el pic hará como si se reseteará también.

Saludos


- La soberbia de un Einstein es entendible.. la de un salame es intolerable (A.Dolina)
- En teoría no hay diferencia entre la teoría y la práctica. En la práctica... si la hay.
- Lee, Lee, Lee y luego pregunta.(maunix)
- Las que conducen y arrastran al mundo no son las máquinas, sino las ideas (V. Hugo)
- Todos los hombres se parecen por sus palabras; solamente las obras evidencian que no son iguales.(Moliere)
- Todo debería ser hecho tan simple como sea posible pero no mas simple que eso.(A.Einstein)

Desconectado rodogodo

  • PIC10
  • *
  • Mensajes: 5
Re: Un macro me resetea el PIC?
« Respuesta #3 en: 04 de Enero de 2007, 17:23:23 »
Muchas gracias Nocturno!!!
Existe un tiempo máximo de resolución de una interrupción en los PICs??,... quiero decir, si no salgo de la rutina de interrupción al cabo de un tiempo,... es posible que se resetee?
Más alla de la pregunta,.. acá envío el programa. Es bastante largo, pero, para hacerla más fácil:
- La rutina de interrupción se llama "Interrupt_Routine". Se accede a ella cada vez que llega un nuevo byte al PIC mediante el USART.
- Al completarse un mensaje (van rodeados por corchetes), se genera la respuesta llamando a "GenerateAnswer" desde la misma rutina de interrupción.
- en la línea 634 y la 651 del Prueba03.asm, están las dos macros del horror!!! Para buscarlas rápidamente se puede buscar la palabra "problema" en el editor. Las macros están PICMACRO.H

Algo más, mientras escribo estoy probando otras alternativas. Lo que hice fue pasar el contenido de una de las macros al programa principal. Con esto, el pic no se reseteó,... pero al darle repetidamente alguno de los comandos complejos, termina colgándose.  :(

Desconectado rodogodo

  • PIC10
  • *
  • Mensajes: 5
Re: Un macro me resetea el PIC?
« Respuesta #4 en: 04 de Enero de 2007, 17:38:11 »
Gracias Mauricio!! Revisé eso también,... He tomado el "guardado de los registros de trabajo" de algunos ejemplos y del pdf de MICROCHIP,... este es:

Interrupt_Routine

movwf   wback      ;Backup del registro de trabajo.
swapf   STATUS,W
clrf   STATUS
movwf   sback      ;Backup del registro de estado.
movf   PCLATH,W
movwf   pcback      ;Backup del PC-H.
clrf   PCLATH
movf   FSR,W
movwf   fsrback      ;Backup del registro FSR

btfsc   PIR1,RCIF      ;Chequea que se haya recibido dato.
call   RX_Data      ;si es asi, corre la rutina de lectura

movf   fsrback,W      ;Restaura el FSR.
movwf   FSR
movf   pcback,W
movwf   PCLATH      ;Restaura el PC-H.
swapf   sback,W
movwf   STATUS      ;Restaura el registro de estado.
swapf   wback,F      ;Restaura el registro de trabajo.
swapf   wback,W

retfie

realmente quisiera que fuera eso,.. pero no creo, ya que el programa funciona bien si solo envío los comandos "simples", lo que me hace pensar que esta rutina está bien. Que te parece?
Gracias,
 Rodolfo

Desconectado maunix

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 4751
    • Mi Sitio Web Personal
Re: Un macro me resetea el PIC?
« Respuesta #5 en: 04 de Enero de 2007, 19:31:51 »
No he revisado todo tu código, tan solo me he centrado en esta parte.

Código: [Seleccionar]
ORG 0x04
goto Interrupt_Routine


¿Puede ser que tu código ocupe más de una página?  Si es así, hacer este tipo de cosas en el vector de interrupción es una muy mala idea.

Es una costumbre que no se de donde sale, pero he visto que muchos usan y realmente es una cosa MUY PELIGROSA.

Si el PCLATH tiene otro valor diferente al de donde está ubicado Interrupt_Routine, tu código no irá ahí sino a otro lado que sería igual offset pero diferente página.

¿Me puedes confirmar esto?
« Última modificación: 04 de Enero de 2007, 19:34:39 por maunix »
- La soberbia de un Einstein es entendible.. la de un salame es intolerable (A.Dolina)
- En teoría no hay diferencia entre la teoría y la práctica. En la práctica... si la hay.
- Lee, Lee, Lee y luego pregunta.(maunix)
- Las que conducen y arrastran al mundo no son las máquinas, sino las ideas (V. Hugo)
- Todos los hombres se parecen por sus palabras; solamente las obras evidencian que no son iguales.(Moliere)
- Todo debería ser hecho tan simple como sea posible pero no mas simple que eso.(A.Einstein)

Desconectado rodogodo

  • PIC10
  • *
  • Mensajes: 5
Re: Un macro me resetea el PIC?
« Respuesta #6 en: 05 de Enero de 2007, 09:13:25 »
El código, por lo que puedo ver en el visor de la memoria de programa, llega hasta la dirección 078C. Esto es, página 0 solamente. De todos modos, el programa no está completo, por lo que me interesa muchísimo lo que me comentás.
Con respecto al "goto", vos como lo harías??,.. ubicarías en la dirección 0x04 el "context saving" y ahí nomás harías un "call" a la rutina que atiende la interrupción?
Como dije antes, sigo probando ideas,.. Lo que hice ahora fue probar lo que sugirió Nocturno,... en la rutina de interrupción levanto un flag y atiendo el comando en el bucle principal. Tendría que bloquear las interrupciones (recepción de nuevos comandos), hasta terminar de atender el actual en el bucle principal, eso no me convence del todo. Igualmente, por lo que estoy viendo hasta el momento, el PIC ha dejado de colgarse y de resetearse,... No entiendo por que! :? Será que realmente no puedo demorar mucho en responder a la interrupción??
En definitiva,.. anda  :-/,... pero no se por que!?!?

Desconectado maunix

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 4751
    • Mi Sitio Web Personal
Re: Un macro me resetea el PIC?
« Respuesta #7 en: 05 de Enero de 2007, 09:44:02 »
Código: [Seleccionar]
[quote author=rodogodo link=topic=15411.msg97317#msg97317 date=1167999205]
El código, por lo que puedo ver en el visor de la memoria de programa, llega hasta la dirección 078C. Esto es, página 0 solamente. De todos modos, el programa no está completo, por lo que me interesa muchísimo lo que me comentás.
Con respecto al "goto", vos como lo harías??,.. ubicarías en la dirección 0x04 el "context saving" y ahí nomás harías un "call" a la rutina que atiende la interrupción?

1) El context saving se DEBE hacer ahí nomás, nada de gotos o calls.  Cualquier otra variante tarde o temprano tendrá problemas y no permite la expansión del código.

2) Un call no lo recomiendo en la rutina de interrupción, gastas una posición del stack.  Usa un goto.  Si atienes una ú otra interrupción, de acuerdo al flag que esté encendido, entonces no veo el motivo por el cual hacer un call.  Al terminar la ejecución de dicho submódulo haces un goto a la parte del código que restaura el contexto.


Como dije antes, sigo probando ideas,.. Lo que hice ahora fue probar lo que sugirió Nocturno,... en la rutina de interrupción levanto un flag y atiendo el comando en el bucle principal. Tendría que bloquear las interrupciones (recepción de nuevos comandos), hasta terminar de atender el actual en el bucle principal, eso no me convence del todo. Igualmente, por lo que estoy viendo hasta el momento, el PIC ha dejado de colgarse y de resetearse,... No entiendo por que! :? Será que realmente no puedo demorar mucho en responder a la interrupción??
En definitiva,.. anda  :-/,... pero no se por que!?!?

¿Haces una restauración del contexto? 

Lo que te sugirió nocturno está muy bien y corresponde a que en general uno quiere que las rutinas de interrupción sean breves, atiendan lo que deban atender y sigan con la ejecución del código en el bucle principal.

En tu caso, pudiera ser que recibas un byte y lo guardes en un buffer cuyo puntero irá incrementándose a medida que recibes más y más bytes.  El flag lo enciendes cuando el buffer esté lleno o cuando tu sepas que has recibido una trama válida.  Pero no te quedas todo el tiempo recibiendo el buffer sin rehabilitar la interrupción.

Tampoco sirve encender un flag para indicar que recibiste un byte de usart, para ello directamente no activas la interrupción de usart y lees su flag.  La técnica del flag sirve con algun "preproceso" previo en la rutina del vector de interrupción, pero este preproceso debe ser breve.  Por preproceso me refiero a que hagas un cálculo, determines si la trama es válida o lo que debas hacer en tu código.

Estuve pensando y también puede ser que tus comandos largos realmente llenen o sobreescriban alguna otra variable, ¿es posible esto?

- La soberbia de un Einstein es entendible.. la de un salame es intolerable (A.Dolina)
- En teoría no hay diferencia entre la teoría y la práctica. En la práctica... si la hay.
- Lee, Lee, Lee y luego pregunta.(maunix)
- Las que conducen y arrastran al mundo no son las máquinas, sino las ideas (V. Hugo)
- Todos los hombres se parecen por sus palabras; solamente las obras evidencian que no son iguales.(Moliere)
- Todo debería ser hecho tan simple como sea posible pero no mas simple que eso.(A.Einstein)

Desconectado rodogodo

  • PIC10
  • *
  • Mensajes: 5
Re: Un macro me resetea el PIC?
« Respuesta #8 en: 15 de Enero de 2007, 09:45:13 »
Muchachos, como les conté, el PIC ya está andando!! Les agradezco mucho su respuesta!! Saludos para todos.  :)