Autor Tema: Entrar a interrupcion en ASM, en entorno C  (Leído 14651 veces)

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

Desconectado Marttyn

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1836
    • IDEAA
Re: Entrar a interrupcion en ASM, en entorno C
« Respuesta #15 en: 06 de Noviembre de 2008, 03:11:10 »
La verdad que si que es un poco confuso lo del direccionamiento indirecto... Y sobre todo, cuando debo o no cambiar de pagina  :z)

Respecto a ésta instrucción "MOVLW PIE1", en realidad no es correcta en la arquitectura 16F, pero verás que el ASM la toma como si lo fuera. Hay una razón muy sencilla. PIE1 en éste caso (aunque sabemos que es el registro PIE1) para el ASM simplemente tiene un valor numérico que es la dirección de dicho registro. Así que el ASM entiende en ésta instrucción lo siguiente:
MOVLW 0x0C, sin saber que te refieres a un registro. Esto es porque en el include se le dió dicho valor a PIE1.

Cuando dices que el include le da el valor 0x0C a PIE1, que significa? o se te "chispoteo" y querias decir 0x8C?
Si es asi, que diferencia hay con usar MOVLW con valores que no son constantes si el compilador los entiende igual?
La gente ve las cosas que existen y se pregunta por qué.
Yo prefiero imaginar lo que no existe y preguntarme por qué no.

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: Entrar a interrupcion en ASM, en entorno C
« Respuesta #16 en: 06 de Noviembre de 2008, 03:37:18 »
Bruno, genial! Simplemente GENIAL!
Que sepas que si te pasas alguna vez por Galicia (España), o si ando por Rosario, te invito unas cervezas, que te las tienes merecidas! :wink:

Me alegro que te pueda ayudar. Obviamente nunca rechazo unas cervezas ;) :D :D  :D

La verdad me ha quedado todo clarisimo!
Excepto esto:  :mrgreen:

*El direccionamiento indirecto que funcion tiene? Si podemos leer el registro directamente, para que lo vamos a leer de manera indirecta? O es para no tener que cambiar de pagina?

Bueno, ya jacrmr ha respondido de una manera bastante peculiar y buena a tus preguntas. Yo voy a intentar hacerte ver para qué serviría en la práctica el direccionamiento indirecto.
Para poder acceder a un registro de manera indirecta, posees 2 registros:
El registro FSR, que es un registro puntero. Es decir, "apunta" o contiene el valor de la posición de memoria a la cual deseás acceder;
Y el registro INDF que contiene el valor del registro al cual FSR apunta en ese momento.

Entonces, supongamos que quiero poner a cero todas la memoria RAM comprendida entre 0x20 y 0x4F.
Si no existiera el direccionamiento indirecto, tendríamos que hacer algo así:

    clrf    0x20
    clrf    0x21
    clrf    0x22
    clrf    0x23
    .....
    clrf    0x4d
    clrf    0x4e
    clrf    0x4f


Lo que sería un verdadero despilfarro de memoria, no?

Ahora, utilizando direccionamiento indirecto, la cosa se torna más sencilla.

         movlw 0x20       ;comienzo desde el registro 0x20
         movwf FSR        ;apunto a dicho registro(ahora, INDF contiene valor del registro 0x20. Todas las operaciones de lectura/escritura sobre el INDF afectarán al registro como si estuviese accediendo directamente a él)
prox  clrf      INDF      ;pongo a cero la posición de memoria a la cual FSR apunta en este momento
         incf     FSR,F     ;indico que quiero acceder a la proxima posicion de memoria
         movf   FSR,w    ;copio el valor de FSR a W
         xorlw  0x50      ;y aplico una XOR para ver si ya he terminado con todos los registros que deseaba limpiar
         btfss   STATUS,Z ;si se cumple, he terminado
         goto    prox         ;no, entonces próximo registro
      
         nop                  ;listo!

Si uso direccionamiento indirecto, en FSR tengo el PORTA por ej, cuando cambie el PORTA, tambien cambiara FSR?

Bueno, supongamos que "en FSR tengo el PORTA": Esto es lo mísmo que decir(en esta familia de PICs) que FSR = 0x05. O sea, que en el registro FSR has cargado el valor 0x05 que corresponde al PORTA. Ahora, si cambiás el valor del PORTA, también cambiará el valor contenido en el registro INDF. No el FSR. El FSR sólo indica el registro al cual acceder. INDF es el que contiene el valor del PORTA, y cambiará si PORTA cambia y viceversa(cambiar el valor del INDF también cambiará el valor del registro 0x05(PORTA)).
¿Se entendió?

Vamos con un ejemplo:
;Supongo que configuré a PORTB todo como salidas y ahora:

     clrf      PORTB      ;ahora, PORTB=0
     movlw 0x06         ;cargo en W la dirección del PORTB(podría haber hecho movlw PORTB)
     movwf FSR          ;ahora, copio el valor de W en el registro FSR. Como W vale 0x06, al cargarlo en el FSR ahora estoy accediendo indirectamente al PORTB.
     bsf    INDF,0        ;ahora, indico que pongo a uno el bit0 del registro INDF. Como INDF contiene el valor del registro PORTB porque FSR apunta a el, ahora el registro PORTB también valdrá 0x01
     clrf     PORTB       ;vuelvo a limpiar el registro PORTB, por lo que INDF también ahora se verá afectado y valdrá 0x00

Es decir que ambos se afectan mutuamente y se comportan como uno sólo(en realidad lo son :D)

Por cierto, cuando tengo que cambiar de pagina? Si estoy en el banco 0, y quiero leer o escribir algo del banco 1 primero tengo que cambiar de pagina? En la pregunta siguiente la instruccion MOVLW lee PIE1 del banco 1, estando en el banco 0 ¿?

Bueno. Esto tiene que ver con la arquitectura de esta familia de microcontroladores. El direccionamiento indirecto posee una ventaja frente al directo. El directo está dividido en bancos de 128 registros cada uno. Esto es por un tema un poco más profundo que no quiero explayar para no marearte.
Lo importante es que mediante el direccionamiento indirecto, podes acceder a cualquiera de los primeros 256 registros sin tener que cambiarlo de banco. Si necesitás acceder a un registro más allá del 0xFF mediante direccionamiento indirecto entonces necesitás setear el bit IRP que mencionaste anteriormente y en este uC no tiene sentido por lo que ya mencionamos.
En definitiva, en este uC que estás usando, podés acceder a toda la RAM sin necesidad de tener precauciones de cambio de banco siempre y cuando lo hagas mediante direccionamiento indirecto. Si usás direccionamento directo, que es más común, necesitás asegurarte que el uC se encuentre en el banco correcto antes de trabajar sobre dicho registro.
Si mirás en las intrucciones en el datasheet vas a ver que en las instrucciones movf, movwf,xorwf, y muchas otras, el registro f debe estar entre 0 y 127. Es decir que cada una de esas instrucciones sólo pueden contener 7bits de direccionamiento. Los otros dos bits(de mayor peso) son dados mediante los bits RP1 y RP0.
Resumiendo:
Si quisiese acceder a PIE1 mediante direccionamiento indirecto sólo me bastaría con hacer:
   movlw  PIE1
   movwf  FSR
   clrf       INDF   ;y aqui leer o escribir directamente el registro INDF

en cambio, si quisiese acceder mediante direccionamiento directo y estuviese en el banco 0:
   bsf  STATUS,RP0           ;cambio al banco1
   clrf    PIE1        ;y ahora si podría trabajar sobre el registro

Citar
La instrucción MOVLW sirve para cargar un LITERAL, es decir un valor pre-establecido. No permite cargar un valor no estático y el contenido de STATUS siempre varía. El movlw carga siempre un valor que tú eliges a la hora de programación. No se puede modificar el valor a cargar en W utilizando la movlw durante la ejecución en el pic(deberías sobrescribir la flash).

Si te fijas, en la linea 21:
Código: ASM
  1. 021    308C     MOVLW PIE1    ;(Cargo en W la dirección a la cual quiero acceder de manera indirecta...es decir, 0x8C)

Aqui estamos cargando en W un valor que no es un "literal". PIE1 se puede modificar en ejecucion o no?

Bueno, esto genera siempre mucha confusión. jacrmr te lo ha explicado más que suficientemente bien.
PIE1 se puede modificar en ejecución. Pero no confundamos el contenido del registro PIE1(que es el que puede cambiar en ejecución) con la dirección en la que se encuentra el registro PIE1(que no cambia).

Hacer MOVLW  PIE1 es exáctamente lo mísmo que hacer movlw 0x0C. Porque como el MPASM espera un literal, un valor incambiable, lo buscará en la definición que hayas hecho de PIE1, y si lo buscas dentro del archivo include(.inc) verás que PIE1 ha sido definido como 0x0C. El ensamblador asume que su valor es 0x0C y lo toma.
Esto permite un código un poco más legible. Obviamente todo depende de la instrucción. Esto se usa mucho en las que aceptan literales como argumentos.

Saludos!
"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

jacrmr

  • Visitante
Re: Entrar a interrupcion en ASM, en entorno C
« Respuesta #17 en: 06 de Noviembre de 2008, 03:40:34 »
Citar
Cuando dices que el include le da el valor 0x0C a PIE1, que significa? o se te "chispoteo" y querias decir 0x8C?
Si es asi, que diferencia hay con usar MOVLW con valores que no son constantes si el compilador los entiende igual?

En efecto, quise decir 0x8C, ya que así está especificado en el include. Pero (espero no confundirte con lo que sigue, en realidad es transparente al usuario y no te debe de preocupar) si tú haces MOVWF PIE1, internamente el PIC te considera el registro como si tuviera un valor de 0x0C, y el bit que lo convierte en 0x8C en realidad es el bit RP0 del STATUS. Y esto debería contestar tu pregunta de por qué es necesario cambiar de páginas (o de bancos en este caso). Los bits de las páginas y los bancos son los bits más signifcativos que forman toda la dirección de la memoria o la dirección de los registros.
Por ejemplo si tú haces MOVWF EECON1, el ASM te genera el mismo código máquina que si hicieras MOVWF PIE1. Los bits RP0 y RP1 del STATUS son los que te forman toda la dirección del registro internamente en el PIC. Y esto nos lleva a lo interesante del ASM y a tu pregunta de que qué diferencia hay si de todas formas le da igual. Este por sí mismo no tiene ambiguedades. Nosotros somos los que podemos incurrir en ellas y es nuestra responsabilidad de que ningún bit de código signifique algo que nosotros no queríamos intencionalmente.

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: Entrar a interrupcion en ASM, en entorno C
« Respuesta #18 en: 06 de Noviembre de 2008, 03:42:37 »
Ehh joer, yo también arrastré ese error :D :D
"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado Leon Pic

  • Colaborador
  • DsPIC30
  • *****
  • Mensajes: 3610
    • Impresiones en 3D
Re: Entrar a interrupcion en ASM, en entorno C
« Respuesta #19 en: 06 de Noviembre de 2008, 10:50:00 »
Aprovechando que se está tratando el tema de los accesos y escribir en forma indirecta, quiero explicar que para grabar en la EEPROM del PIC para el usuario, se hace también en forma indirecta, más precisamente con los registro EEADR y EEDATA (en algunos PIC, como al 16F877, se agregan dos más que son para la parte alta EEADRH y EEDATAH).

Bien, EEADR significa EE: EEPROM y ADR: Address (dirección)----- EEDATA: EEPROM y DATA: DATA (datos).

Para grabar un dato en una pocición determinada, primero tengo que cargar en EEADR la dirección. Y en EEDATA el valor propiamente dicho para guardar en la pocición designada en EEADR.

Por ejemplo:

Código: ASM
  1. MOVLW       H'23'       ;Cargo a W con el valor H'23'
  2.         MOVWF       EEADR    ;y lo muevo a EEADR para apuntar la pocición H'23'
  3.         MOVLW       H'12'       ;Cargo a W con el valor H'12'
  4.         MOVWF       EEDATA  ;y lo muevo a EEDATA para guardar el valor deseado.

Si logran entender este ejemplo, pasa lo mismo con INDF y FSR. INDF hace el mismo trabajo que EEADR y FSR hace el mismo trabajo que EEDATA.

Todo esto, pronto lo explicaré en ASM desde 0
Jesús dijo, yo soy el CAMINO, la VERDAD y la VIDA, nadie llega al PADRE si no es por mi.

Desconectado Marttyn

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1836
    • IDEAA
Re: Entrar a interrupcion en ASM, en entorno C
« Respuesta #20 en: 07 de Noviembre de 2008, 01:55:49 »
Bueno, deje "macerar" mis conocimientos recientemente aprendidos. Dormi, pense en otras cosas, estuve con mi novia, lei, di una vuelta.... Y ahora volvi a leer todo de nuevo para asentar lo aprendido. La verdad creo que ya lo tengo todo MUCHO mas claro! Creo que incluso entiendo el direccionamiento indirecto!  :D

Leo, jacrmr, tambien os mereceis una cervecita! Si quereis probar una "Duff" (la de los simpson) aqui en Galicia las tenemos!



Bruno, tu comentaste antes que que este codigo de interrupcion deja bastante que desear, y que hay unas cuantas lineas que se pueden "unir" para hacer el codigo mas corto. Podrias indicarme cuales? Esas son las cosas que no vienen en los manuales y que solo se aprenden con la experiencia... o si te las dice otro  :D

Salu2
La gente ve las cosas que existen y se pregunta por qué.
Yo prefiero imaginar lo que no existe y preguntarme por qué no.

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: Entrar a interrupcion en ASM, en entorno C
« Respuesta #21 en: 07 de Noviembre de 2008, 03:26:27 »
Hola!

Te comento cómo lo dejaría yo:

1er paso: Renombrar un poco las cosas para que sea un poco más legible;

Código: ASM
  1. 004    1A83     BTFSC STATUS, RP0
  2.   005    280A     GOTO 0xa
  3.   006    00A5     MOVWF W_AUX           ;0x25
  4.   007    0E03     SWAPF STATUS, W
  5.   008    00A6     MOVWF S_AUX           ;0x26
  6.   009    280F     GOTO 0xf
  7.   00A    1283     BCF STATUS, RP0
  8.   00B    00A5     MOVWF W_AUX
  9.   00C    0E03     SWAPF STATUS, W
  10.   00D    00A6     MOVWF S_AUX
  11.   00E    14A6     BSF S_AUX, 1         
  12.   00F    080A     MOVF PCLATH, W
  13.   010    00AD     MOVWF P_AUX           ;0x2d
  14.   011    018A     CLRF PCLATH
  15.   012    1383     BCF STATUS, IRP
  16.   013    0EA5     SWAPF W_AUX, F
  17.   014    0804     MOVF FSR, W
  18.   015    00A7     MOVWF F_AUX           ;0x27
  19.   016    0820     MOVF REG1, W          ;0x20
  20.   017    00A8     MOVWF R1_AUX          ;0x28
  21.   018    0821     MOVF REG2, W          ;0x21
  22.   019    00A9     MOVWF R2_AUX          ;0x29
  23.   01A    0822     MOVF REG3, W          ;0x22
  24.   01B    00AA     MOVWF R3_AUX          ;0x2a
  25.   01C    0823     MOVF REG4, W          ;0x23
  26.   01D    00AB     MOVWF R4_AUX          ;0x2b
  27.   01E    0824     MOVF REG5, W          ;0x25
  28.   01F    00AC     MOVWF R5_AUX          ;0x2c
  29.   020    1283     BCF STATUS, RP0
  30.   021    308C     MOVLW PIE1
  31.   022    0084     MOVWF FSR
  32.   023    1C00     BTFSS INDF, TMR1IE
  33.   024    2827     GOTO 0x27
  34.   025    180C     BTFSC PIR1, TMR1IF
  35.   026    2850     GOTO 0x50
  36.   027    308C     MOVLW PIE1
  37.   028    0084     MOVWF FSR
  38.   029    1C80     BTFSS INDF, TMR2IE
  39.   02A    282D     GOTO 0x2d
  40.   02B    188C     BTFSC PIR1, TMR2IF
  41.   02C    2857     GOTO 0x57
  42.   02D    1E8B     BTFSS INTCON, TMR0IE
  43.   02E    2831     GOTO 0x31
  44.   02F    190B     BTFSC INTCON, TMR0IF
  45.   030    284C     GOTO 0x4c
  46.   031    308C     MOVLW PIE1
  47.   032    0084     MOVWF FSR
  48.   033    1E80     BTFSS INDF, RCIE
  49.   034    2837     GOTO 0x37
  50.   035    1A8C     BTFSC PIR1, RCIF
  51.   036    285B     GOTO 0x5b
  52.   037    0827     MOVF F_AUX, W
  53.   038    0084     MOVWF FSR
  54.   039    0828     MOVF R1_AUX, W
  55.   03A    00A0     MOVWF REG1
  56.   03B    0829     MOVF R2_AUX, W
  57.   03C    00A1     MOVWF REG2
  58.   03D    082A     MOVF R3_AUX, W
  59.   03E    00A2     MOVWF REG3
  60.   03F    082B     MOVF R4_AUX, W
  61.   040    00A3     MOVWF REG4
  62.   041    082C     MOVF R5_AUX, W
  63.   042    00A4     MOVWF REG5
  64.   043    082D     MOVF P_AUX, W
  65.   044    008A     MOVWF PCLATH
  66.   045    0E26     SWAPF S_AUX, W
  67.   046    0083     MOVWF STATUS
  68.   047    1283     BCF STATUS, RP0
  69.   048    0E25     SWAPF W_AUX, W
  70.   049    18A6     BTFSC S_AUX, 1
  71.   04A    1683     BSF STATUS, RP0
  72.   04B    0009     RETFIE

2do paso: Comentar un poco

Código: ASM
  1. 004    1A83     BTFSC STATUS, RP0               ;Banco 0?
  2.   005    280A     GOTO 0xa                      ;No. Saltar
  3.   006    00A5     MOVWF W_AUX           ;0x25   ;Si. Guardar W
  4.   007    0E03     SWAPF STATUS, W               ;Guardar STATUS
  5.   008    00A6     MOVWF S_AUX           ;0x26
  6.   009    280F     GOTO 0xf                      ;y saltar
  7.   00A    1283     BCF STATUS, RP0               ;Banco 1. Volver a banco 0
  8.   00B    00A5     MOVWF W_AUX                   ;Guardar W
  9.   00C    0E03     SWAPF STATUS, W               ;Guardar STATUS
  10.   00D    00A6     MOVWF S_AUX  
  11.   00E    14A6     BSF S_AUX, 1          ;1      ;RECORDAR QUE ESTABA EN EL BANCO 1!
  12.   00F    080A     MOVF PCLATH, W                ;Guardar PCLATH
  13.   010    00AD     MOVWF P_AUX           ;0x2d
  14.   011    018A     CLRF PCLATH                   ;Limpiar PCLATH
  15.   012    1383     BCF STATUS, IRP               ;Limpiar IRP
  16.   013    0EA5     SWAPF W_AUX, F                ;Swapear W_AUX
  17.   014    0804     MOVF FSR, W                   ;Guardar FSR
  18.   015    00A7     MOVWF F_AUX           ;0x27   ;Y otros registros usados
  19.   016    0820     MOVF REG1, W          ;0x20
  20.   017    00A8     MOVWF R1_AUX          ;0x28
  21.   018    0821     MOVF REG2, W          ;0x21
  22.   019    00A9     MOVWF R2_AUX          ;0x29
  23.   01A    0822     MOVF REG3, W          ;0x22
  24.   01B    00AA     MOVWF R3_AUX          ;0x2a
  25.   01C    0823     MOVF REG4, W          ;0x23
  26.   01D    00AB     MOVWF R4_AUX          ;0x2b
  27.   01E    0824     MOVF REG5, W          ;0x25
  28.   01F    00AC     MOVWF R5_AUX          ;0x2c
  29.   020    1283     BCF STATUS, RP0               ;Banco 0
  30.   021    308C     MOVLW PIE1                    ;Verificacion de si Timer1 interrumpió
  31.   022    0084     MOVWF FSR
  32.   023    1C00     BTFSS INDF, TMR1IE
  33.   024    2827     GOTO 0x27
  34.   025    180C     BTFSC PIR1, TMR1IF
  35.   026    2850     GOTO 0x50
  36.   027    308C     MOVLW PIE1                    ;Verificacion de si Timer1 interrumpió
  37.   028    0084     MOVWF FSR
  38.   029    1C80     BTFSS INDF, TMR2IE
  39.   02A    282D     GOTO 0x2d
  40.   02B    188C     BTFSC PIR1, TMR2IF
  41.   02C    2857     GOTO 0x57
  42.   02D    1E8B     BTFSS INTCON, TMR0IE          ;Verificacion de si Timer0 interrumpió
  43.   02E    2831     GOTO 0x31
  44.   02F    190B     BTFSC INTCON, TMR0IF
  45.   030    284C     GOTO 0x4c
  46.   031    308C     MOVLW PIE1                    ;Verificacion de si USART interrumpió
  47.   032    0084     MOVWF FSR
  48.   033    1E80     BTFSS INDF, RCIE
  49.   034    2837     GOTO 0x37
  50.   035    1A8C     BTFSC PIR1, RCIF
  51.   036    285B     GOTO 0x5b
  52.   037    0827     MOVF F_AUX, W                 ;Restaurar registros...
  53.   038    0084     MOVWF FSR
  54.   039    0828     MOVF R1_AUX, W
  55.   03A    00A0     MOVWF REG1
  56.   03B    0829     MOVF R2_AUX, W
  57.   03C    00A1     MOVWF REG2
  58.   03D    082A     MOVF R3_AUX, W
  59.   03E    00A2     MOVWF REG3
  60.   03F    082B     MOVF R4_AUX, W
  61.   040    00A3     MOVWF REG4
  62.   041    082C     MOVF R5_AUX, W
  63.   042    00A4     MOVWF REG5
  64.   043    082D     MOVF P_AUX, W
  65.   044    008A     MOVWF PCLATH
  66.   045    0E26     SWAPF S_AUX, W
  67.   046    0083     MOVWF STATUS
  68.   047    1283     BCF STATUS, RP0
  69.   048    0E25     SWAPF W_AUX, W
  70.   049    18A6     BTFSC S_AUX, 1
  71.   04A    1683     BSF STATUS, RP0
  72.   04B    0009     RETFIE

3er paso: Optimizarla y reubicarla

Código: ASM
  1. 004      ????     BCF   R1_AUX,0                ;Incicializo indicando que estaba en banco0
  2.   005    1A83     BTFSC STATUS, RP0             ;Banco 0?
  3.   006    ????     BSF   R1_AUX,0                ;No. Entonces guardo que estaba en el banco1
  4.  
  5.   007    ????     CLRF  STATUS                  ;Banco0
  6.   008    00A5     MOVWF W_AUX           ;0x25   ;Guardar W             
  7.   009    0E03     SWAPF STATUS, W               ;Guardar STATUS
  8.   00A    00A6     MOVWF S_AUX           ;0x26
  9.   00B    ????     BTFSC R1_AUX,0                ;Ingreso estando en el banco0?
  10.   00C    14A6     BSF S_AUX, 1                  ;No.Guardar que estaba en el banco1
  11. ;GUARDA OTROS REGISTROS CLAVE
  12.   00D    080A     MOVF PCLATH, W                ;Guardar PCLATH
  13.   00E    00AD     MOVWF P_AUX           ;0x2d
  14.   00F    018A     CLRF PCLATH                   ;Limpiar PCLATH
  15.   010    0804     MOVF FSR, W                   ;Guardar FSR
  16.   011    00A7     MOVWF F_AUX           ;0x27   ;Y otros registros usados
  17.   012    0820     MOVF REG1, W          ;0x20
  18.   013    00A8     MOVWF R1_AUX          ;0x28
  19.   014    0821     MOVF REG2, W          ;0x21
  20.   015    00A9     MOVWF R2_AUX          ;0x29
  21.  
  22. TIMER0
  23.   016    1E8B     BTFSC INTCON, TMR0IE          ;Verificacion de si Timer0 interrumpió
  24.   017    190B     BTFSS INTCON, TMR0IF
  25.   018    284C     GOTO 0x4c                     ;TIMER0 ISR
  26.  
  27.   019    308C     MOVLW PIE1
  28.   01A    0084     MOVWF FSR
  29.  
  30. TIMER1
  31.   01B    1C00     BTFSC INDF, TMR1IE
  32.   01C    180C     BTFSS PIR1, TMR1IF
  33.   01D    2850     GOTO 0x50                     ;TIMER1 ISR
  34.  
  35. TIMER2
  36.   01E    1C80     BTFSC INDF, TMR2IE
  37.   01F    188C     BTFSS PIR1, TMR2IF
  38.   020    2857     GOTO 0x57                     ;TIMER2 ISR
  39.  
  40. USART
  41.   021    1E80     BTFSC INDF, RCIE
  42.   022    1A8C     BTFSS PIR1, RCIF
  43.   023    285B     GOTO 0x5b                     ;USART ISR
  44.  
  45. RESTAURAR
  46.   024    0827     MOVF F_AUX, W                 ;Restaurar registros...
  47.   025    0084     MOVWF FSR
  48.   026    0828     MOVF R1_AUX, W
  49.   027    00A0     MOVWF REG1
  50.   028    0829     MOVF R2_AUX, W
  51.   029    00A1     MOVWF REG2
  52.   02A    082D     MOVF P_AUX, W
  53.   02B    008A     MOVWF PCLATH
  54.   02C    0E26     SWAPF S_AUX, W
  55.   02D    0083     MOVWF STATUS
  56.   02E    1283     BCF STATUS, RP0
  57.   02F    0EA5     SWAPF W_AUX, F                ;Swapear W_AUX
  58.   030    0E25     SWAPF W_AUX, W
  59.   031    18A6     BTFSC S_AUX, 1
  60.   032    1683     BSF STATUS, RP0
  61.   033    0009     RETFIE

4to paso: Segunda optimización(esta requiere que 0x2C no sea usada nunca en el programa! ojo! aprovecho que no se usa para guardar el banco(RP0)

Código: ASM
  1. 004      ????     BCF   0x2C,RP0                ;Incicializo indicando que estaba en banco0
  2.   005    1A83     BTFSC STATUS, RP0             ;Banco 0?
  3.   006    ????     BSF   0x2C,RP0                ;No. Entonces guardo que estaba en el banco1
  4.  
  5.   007    ????     CLRF  STATUS                  ;Banco0
  6.   008    00A5     MOVWF W_AUX           ;0x25   ;Guardar W             
  7.   009    0E03     SWAPF STATUS, W               ;Guardar STATUS
  8.   00A    00A6     MOVWF S_AUX           ;0x26
  9.  
  10. ;GUARDA OTROS REGISTROS CLAVE
  11.   00B    080A     MOVF PCLATH, W                ;Guardar PCLATH
  12.   00C    00AD     MOVWF P_AUX           ;0x2d
  13.   00D    018A     CLRF PCLATH                   ;Limpiar PCLATH
  14.   00E    0804     MOVF FSR, W                   ;Guardar FSR
  15.   00F    00A7     MOVWF F_AUX           ;0x27   ;Y otros registros usados
  16.   010    0820     MOVF REG1, W          ;0x20
  17.   011    00A8     MOVWF R1_AUX          ;0x28
  18.   012    0821     MOVF REG2, W          ;0x21
  19.   013    00A9     MOVWF R2_AUX          ;0x29
  20.  
  21. TIMER0
  22.   014    1E8B     BTFSC INTCON, TMR0IE          ;Verificacion de si Timer0 interrumpió
  23.   015    190B     BTFSS INTCON, TMR0IF
  24.   016    284C     GOTO 0x4c                     ;TIMER0 ISR
  25.  
  26.   017    308C     MOVLW PIE1
  27.   018    0084     MOVWF FSR
  28.  
  29. TIMER1
  30.   019    1C00     BTFSC INDF, TMR1IE
  31.   01A    180C     BTFSS PIR1, TMR1IF
  32.   01B    2850     GOTO 0x50                     ;TIMER1 ISR
  33.  
  34. TIMER2
  35.   01C    1C80     BTFSC INDF, TMR2IE
  36.   01D    188C     BTFSS PIR1, TMR2IF
  37.   01E    2857     GOTO 0x57                     ;TIMER2 ISR
  38.  
  39. USART
  40.   01F    1E80     BTFSC INDF, RCIE
  41.   020    1A8C     BTFSS PIR1, RCIF
  42.   021    285B     GOTO 0x5b                     ;USART ISR
  43.  
  44. RESTAURAR
  45.   022    0827     MOVF F_AUX, W                 ;Restaurar registros...
  46.   023    0084     MOVWF FSR
  47.   024    0828     MOVF R1_AUX, W
  48.   025    00A0     MOVWF REG1
  49.   026    0829     MOVF R2_AUX, W
  50.   027    00A1     MOVWF REG2
  51.   028    082D     MOVF P_AUX, W
  52.   029    008A     MOVWF PCLATH
  53.   02A    0E26     SWAPF S_AUX, W
  54.   02B    0083     MOVWF STATUS
  55.   02C    0EA5     SWAPF W_AUX, F                ;Swapear W_AUX
  56.   02D    0E25     SWAPF W_AUX, W
  57.   02E    18A6     BTFSC 0x2C, RP0
  58.   02F    1683     BSF STATUS, RP0
  59.   030    0009     RETFIE

Saludos.
"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado Marttyn

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1836
    • IDEAA
Re: Entrar a interrupcion en ASM, en entorno C
« Respuesta #22 en: 08 de Noviembre de 2008, 03:28:49 »
Hola Bruno! Gracias por ayudarme a optimizar el codigo!
La verdad que tuve que estrujarme un poco los sesos para entender porque haces lo que haces cuando entras en el vector de interrupcion, aunque creo que ya lo cacé.
Solo hay una cosita que no consigo entender, porque la segunda optimizacion ocupa mas instrucciones que la primera? Puede ser que las hayas puesto al reves? Sino tampoco me cuadra lo de no poder usar el registro 0x2C en todo el programa.

Y ahora me dejo de preguntas y me someto a "examen". Aplicando todo lo aprendido sobre direccionamiento directo e indirecto quiero ver si apruebo con el siguiente codigo:

Código: ASM
  1. 004    MOVWF    0x70
  2. 005    SWAPF    STATUS, W
  3. 006    MOVWF    0x71
  4. .
  5. .
  6. .
  7. [Todo el resto]

Sencillo... Jeje... Ahora explico lo que hace, o al menos lo que me gustaria que haga  :D
El codigo original, y el de Bruno hacen una comprobacion para ver en que banco se encuentrar para poder luego ir al banco 0 y salvar el contexto. Este codigo lo que hace es no preocuparse de ver en que banco estamos, aprovechar el direccionamiento directo, que solo son 7 bits y asi grabar en la posicion 70h el contenido de W, y en 71h el contenido de STATUS. No nos importa en que banco estemos porque si estamos en el banco 1, y grabamos en el registro 70h, estaremos grabando en realidad en el registro F0h (esto lo aprendi de jacrmr  :mrgreen:). Y si estamos en el banco 0, y grabamos en el registro 70h, estaremos grabando exactamente en ese registro (obvio). Lo bonito de esto es que los registros del F0h al FFh acceden directamente a los registros 70h al 7Fh, por lo que siempre estaremos grabando en el banco 0, aunque nos encontremos en el banco 1. De esta manera nos ahorramos la comprobacion del principio y usar mas memoria de la necesaria... Y lo mas interesante para tener los tiempos controlados es evitar que el programa se bifurque consumiendo 1 o 2 ciclos dependiendo de algunas cosas.
Que opinas? Estoy aprobado? o la teoria es muy bonita pero estoy dando palos de ciego?  :D

PS: por cierto, al compilar en C, se genera algun archivo en ASM que pueda cargar y modificar directamente desde MPASM? Porque el .lst no se si sera "apto".
« Última modificación: 08 de Noviembre de 2008, 03:51:21 por Marttyn »
La gente ve las cosas que existen y se pregunta por qué.
Yo prefiero imaginar lo que no existe y preguntarme por qué no.

jacrmr

  • Visitante
Re: Entrar a interrupcion en ASM, en entorno C
« Respuesta #23 en: 08 de Noviembre de 2008, 04:00:17 »
Supongo que ya lo sabes de antemano, pero en "Archivos de Programa\Microchip\MPASM Suite\Template\Code" se encuentran todos los templates para cada microcontrolador. Ahí puedes observar como Microchip recomienda e implementa la entrada y salida de las interrupciones y el porqué de usar los registros arriba de 0x70. No hay necesidad de saber en qué banco te encuentras cuando entras a salvar el contexto del programa. La hay cuando ya salvaste el contexto y empiezas a hacer tu rutina de interrupción.

Código: ASM
  1. ;**********************************************************************
  2. ;   This file is a basic code template for assembly code generation   *
  3. ;   on the PICmicro PIC16F877A. This file contains the basic code     *
  4. ;   building blocks to build upon.                                    *  
  5. ;                                                                     *
  6. ;   If interrupts are not used all code presented between the ORG     *
  7. ;   0x004 directive and the label main can be removed. In addition    *
  8. ;   the variable assignments for 'w_temp' and 'status_temp' can       *
  9. ;   be removed.                                                       *                        
  10. ;                                                                     *
  11. ;   Refer to the MPASM User's Guide for additional information on     *
  12. ;   features of the assembler (Document DS33014).                     *
  13. ;                                                                     *
  14. ;   Refer to the respective PICmicro data sheet for additional        *
  15. ;   information on the instruction set.                               *
  16. ;                                                                     *
  17. ;**********************************************************************
  18. ;                                                                     *
  19. ;    Filename:      xxx.asm                                           *
  20. ;    Date:                                                            *
  21. ;    File Version:                                                    *
  22. ;                                                                     *
  23. ;    Author:                                                          *
  24. ;    Company:                                                         *
  25. ;                                                                     *
  26. ;                                                                     *
  27. ;**********************************************************************
  28. ;                                                                     *
  29. ;    Files required:                                                  *
  30. ;                                                                     *
  31. ;                                                                     *
  32. ;                                                                     *
  33. ;**********************************************************************
  34. ;                                                                     *
  35. ;    Notes:                                                           *
  36. ;                                                                     *
  37. ;                                                                     *
  38. ;                                                                     *
  39. ;                                                                     *
  40. ;**********************************************************************
  41.  
  42.  
  43.         list            p=16f877A       ; list directive to define processor
  44.         #include        <p16f877A.inc; processor specific variable definitions
  45.        
  46.         __CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_ON & _RC_OSC & _WRT_OFF & _LVP_ON & _CPD_OFF
  47.  
  48. ; '__CONFIG' directive is used to embed configuration data within .asm file.
  49. ; The lables following the directive are located in the respective .inc file.
  50. ; See respective data sheet for additional information on configuration word.
  51.  
  52.  
  53.  
  54.  
  55.  
  56.  
  57. ;***** VARIABLE DEFINITIONS
  58. w_temp          EQU     0x71            ; variable used for context saving
  59. status_temp     EQU     0x72            ; variable used for context saving
  60. pclath_temp     EQU     0x73            ; variable used for context saving                     
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67. ;**********************************************************************
  68.         ORG     0x000             ; processor reset vector
  69.  
  70.         nop                       ; nop required for icd
  71.         goto    main              ; go to beginning of program
  72.  
  73.  
  74.         ORG     0x004             ; interrupt vector location
  75.  
  76.         movwf   w_temp            ; save off current W register contents
  77.         movf    STATUS,w          ; move status register into W register
  78.         movwf   status_temp       ; save off contents of STATUS register
  79.         movf    PCLATH,w          ; move pclath register into w register
  80.         movwf   pclath_temp       ; save off contents of PCLATH register
  81.  
  82. ; isr code can go here or be located as a call subroutine elsewhere
  83.  
  84.         movf    pclath_temp,w     ; retrieve copy of PCLATH register
  85.         movwf   PCLATH            ; restore pre-isr PCLATH register contents
  86.         movf    status_temp,w     ; retrieve copy of STATUS register
  87.         movwf   STATUS            ; restore pre-isr STATUS register contents
  88.         swapf   w_temp,f
  89.         swapf   w_temp,w          ; restore pre-isr W register contents
  90.         retfie                    ; return from interrupt
  91.  
  92.  
  93.  
  94. main
  95.  
  96. ; remaining code goes here
  97.  
  98.  
  99.  
  100.  
  101.  
  102.  
  103.  
  104.  
  105.  
  106.  
  107.         END                       ; directive 'end of program'

« Última modificación: 08 de Noviembre de 2008, 04:09:07 por jacrmr »

Desconectado Marttyn

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1836
    • IDEAA
Re: Entrar a interrupcion en ASM, en entorno C
« Respuesta #24 en: 08 de Noviembre de 2008, 04:08:13 »
Supongo que ya lo sabes de antemano, pero en "Archivos de Programa\Microchip\MPASM Suite\Template\Code" se encuentran todos los templates para cada microcontrolador. Ahí puedes observar como Microchip recomienda e implementa la entrada y salida de las interrupciones y el porqué de usar los registros arriba de 0x70.

 :shock: :shock: :shock:
 :5] :5] :5]
Yo creia que se me habia ocurrido algo GENIAL... Llevo HORAS tratando de ingeniarmelas para esquivar los BTF
:8} :8} :8}

Bueno... no se puede reinventar la rueda... pero al menos me queda el consuelo de saber que lo descubri solito   :P
La gente ve las cosas que existen y se pregunta por qué.
Yo prefiero imaginar lo que no existe y preguntarme por qué no.

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: Entrar a interrupcion en ASM, en entorno C
« Respuesta #25 en: 08 de Noviembre de 2008, 08:59:35 »
Buenas

Bueno, yo también ya sabía eso, pero pensé que la idea tampoco era
Solo hay una cosita que no consigo entender, porque la segunda optimizacion ocupa mas instrucciones que la primera? Puede ser que las hayas puesto al reves?

Hmm...según lo que yo veo, la 2da ocupa 3 instrucciones menos que la 1era, o estaré loco?

Sino tampoco me cuadra lo de no poder usar el registro 0x2C en todo el programa.

El 0x2C lo usé como bit auxiliar para recordar el banco al ingresar a la ISR. Si el compilador usara ese registro, se destruiría dentro de la ISR desde qué banco ingresó. :)

Y ahora me dejo de preguntas y me someto a "examen". Aplicando todo lo aprendido sobre direccionamiento directo e indirecto quiero ver si apruebo con el siguiente codigo:

Código: ASM
  1. 004    MOVWF    0x70
  2. 005    SWAPF    STATUS, W
  3. 006    MOVWF    0x71
  4. .
  5. .
  6. .
  7. [Todo el resto]

Sencillo... Jeje... Ahora explico lo que hace, o al menos lo que me gustaria que haga  :D
El codigo original, y el de Bruno hacen una comprobacion para ver en que banco se encuentrar para poder luego ir al banco 0 y salvar el contexto. Este codigo lo que hace es no preocuparse de ver en que banco estamos, aprovechar el direccionamiento directo, que solo son 7 bits y asi grabar en la posicion 70h el contenido de W, y en 71h el contenido de STATUS. No nos importa en que banco estemos porque si estamos en el banco 1, y grabamos en el registro 70h, estaremos grabando en realidad en el registro F0h (esto lo aprendi de jacrmr  :mrgreen:). Y si estamos en el banco 0, y grabamos en el registro 70h, estaremos grabando exactamente en ese registro (obvio). Lo bonito de esto es que los registros del F0h al FFh acceden directamente a los registros 70h al 7Fh, por lo que siempre estaremos grabando en el banco 0, aunque nos encontremos en el banco 1. De esta manera nos ahorramos la comprobacion del principio y usar mas memoria de la necesaria... Y lo mas interesante para tener los tiempos controlados es evitar que el programa se bifurque consumiendo 1 o 2 ciclos dependiendo de algunas cosas.
Que opinas? Estoy aprobado? o la teoria es muy bonita pero estoy dando palos de ciego?  :D

PS: por cierto, al compilar en C, se genera algun archivo en ASM que pueda cargar y modificar directamente desde MPASM? Porque el .lst no se si sera "apto".

Ja ja. No hombre, muy bien! Creeme que cuando yo había empezado con ASM no se me hubiese ocurrido. Si, los 16 registros son muy útiles para lograr lo que querés. Yo no me fui fuera de lo que el  compilador pretendía. Pensé que no querías tocar esos registros ni ningúno fuera de los que el CCS ya utilizaba. Obviamente que vale siempre y cuando no esté el CCS usandolos a dichos registros(los que elijas entre los 16 que hay).

Y jacrmr, no seas tan duro con el chico, eh? :P :D

Saludos

"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

jacrmr

  • Visitante
Re: Entrar a interrupcion en ASM, en entorno C
« Respuesta #26 en: 08 de Noviembre de 2008, 13:51:53 »
Citar
Y jacrmr, no seas tan duro con el chico, eh? 


No, para nada. Al contrario, me entusiasma mucho cuando alguien le toma interés al ASM.

Desconectado Marttyn

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1836
    • IDEAA
Re: Entrar a interrupcion en ASM, en entorno C
« Respuesta #27 en: 08 de Noviembre de 2008, 16:07:34 »
jacrmr, no seas tan duro conmigo, eh!  :D :D :D

Disculpa bruno, tienes razon, el 4º codigo esta mas optimizado que el tercero... lo que paso fue que al imprimirlos para analizarlos los mezcle y les puse el titulo intercambiado. Por eso mismo tampoco me cuadraba lo del registro auxiliar 0x2C  :oops:

Gracias a todos por la ayuda prestada! Creo que a estas alturas ya puedo armar mi propia rutina de ISR  :-/
La gente ve las cosas que existen y se pregunta por qué.
Yo prefiero imaginar lo que no existe y preguntarme por qué no.

Desconectado Marttyn

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1836
    • IDEAA
Re: Entrar a interrupcion en ASM, en entorno C
« Respuesta #28 en: 10 de Noviembre de 2008, 00:02:50 »
Hola otra vez! 
ESTOY FELIZ :mrgreen:
Mirad lo que encontre en la ayuda del CCS:
Citar
Syntax:
 #int_global
 
Elements:
 None
 
Purpose:
 This directive causes the following function to replace the compiler interrupt dispatcher.  The function is normally not required and should be used with great caution.  When used, the compiler does not generate start-up code or clean-up code, and does not save the registers.
 
Examples:
 
Código: C
  1. #int_global
  2. isr() {     // Will be located at location 4 for PIC16 chips.
  3.    #asm
  4.    bsf   isr_flag
  5.    retfie
  6.    #endasm
  7. }

Es lo que creo que es, no?
Si es asi me ahorro el tener que andar compilando el programa en C, y luego modificar el ASM generado cada vez que quiero hacer una prueba!
Eso si, la ISR la escribire en ASM igualmente, ya que de lo que trataba todo esto era de que lSR "midiera" exactamente lo que yo necesito.
Salu2!
La gente ve las cosas que existen y se pregunta por qué.
Yo prefiero imaginar lo que no existe y preguntarme por qué no.

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: Entrar a interrupcion en ASM, en entorno C
« Respuesta #29 en: 10 de Noviembre de 2008, 01:11:34 »
Así es..Congratulations! yo nunca supe de su existencia :D

Saludos
"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.


 

anything