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

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

Desconectado Marttyn

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1836
    • IDEAA
Entrar a interrupcion en ASM, en entorno C
« en: 04 de Noviembre de 2008, 01:08:44 »
Hola!
Vengo de otro post:
http://www.todopic.com.ar/foros/index.php?topic=23351.msg189945#msg189945
Aqui hablan algunas cosas muy interesantes sobre "retrasos" del timer0. Alli me di cuenta de unas cosas, pero como no pertenecian al tema principal, y para no desviarlo prefiero abrir un tema nuevo.

Me gustaria poder modificar las instrucciones generadas para la "entrada" y "salida" de las interrupciones por el compilador C (en mi programa se generan a partir de la linea 4 de codigo ASM hasta el RETFIE).
Digo esto porque tal cual genera el ASM el CCS, una misma interrupcion no siempre tarda lo mismo desde que se produce la interrupcion hasta llegar a la primera instruccion de la misma, ya que depende en que pagina estemos, que valores tengan algunos registros, etc...
Estoy haciendo un programa que requiere bastante precision, y quiero tener medidos todos los tiempos, pero solo con C no soy capaz, y quiero hacerlo en ASM, pero desde el CCS no se como  :(
Alguna idea?

PS: ayer --> ASM = CHINO
hoy imprimi y encuaderne todo el datasheet de mi pic y llevo todo el dia mirando instruccion por instruccion que significa cada cosa y comparandolo con mi codigo C, y la verdad es entretenido ASM  :mrgreen:
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 #1 en: 04 de Noviembre de 2008, 01:27:59 »
Sin ningún interés de calentar los ánimos entre la ya tan conocida discusión de "qué es mejor, si ASM ó C", sin duda alguna has llegado al punto de que una aplicación la debes hacer forzosamente en ASM ya que el C no fue funcional. Definitivamente creo que "maquillar" la salida del compilador de C ajustando tú mismo el ASM no es lo más conveniente. No te va a quedar otra que aprender ASM, así que no te desanimes. No es tan difícil como parece y al final te acostumbrarás a tener ambos bandos, C y ASM, según cuando requieras aplicaciones en donde cada ciclo de instrucción cuenta, como trabajar con video por ejemplo; las sólas instrucciones del reestablecimiento del stack o de variables en C son suficientes para que se pierda el sincronismo o el trazo adecuado del video.

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: Entrar a interrupcion en ASM, en entorno C
« Respuesta #2 en: 04 de Noviembre de 2008, 02:45:04 »
Hola Marttyn.

Bueno, como primera instancia sería bueno que publiques el código C de las interrupciones, y su correspondiente asm generado de salida como para poder ir ayudandote y orientandote.

Es importante que lo hagas vos, porque eso depende inclusive de la versión del compilador que estés usando.

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 #3 en: 04 de Noviembre de 2008, 11:31:32 »
Este es el codigo C que estoy usando para hacer pruebas. Simplemente lo uso para hacer saltar las interrupciones y ver que codigo genera cada cosa y como optimizarlo.

Código: C
  1. #include <12F683.h>
  2. #device adc=8
  3.  
  4. #FUSES NOWDT,NOMCLR,PUT,INTRC_IO
  5. #use delay(clock=4000000)
  6.  
  7. #int_TIMER0
  8. void TIMER0_isr(void) {
  9.         delay_cycles(1);
  10. }
  11. #int_TIMER1
  12. void TIMER1_isr(void) {
  13.         //delay_cycles(1);
  14.         set_timer1(45574);
  15. }
  16. #int_TIMER2
  17. void TIMER2_isr(void) {
  18.         delay_cycles(1);
  19. }
  20. #int_CCP1
  21. void CCP1_isr(void){
  22.         delay_cycles(1);
  23. }
  24. void main() {
  25.        
  26.         setup_adc_ports(NO_ANALOGS|VSS_VDD);
  27.         setup_adc(ADC_CLOCK_INTERNAL);
  28.         setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
  29.         setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
  30.         setup_timer_2(T2_DIV_BY_1,255,1);
  31.         setup_ccp1(CCP_COMPARE_INT);
  32.         setup_comparator(NC_NC);
  33.         setup_vref(FALSE);
  34.         //enable_interrupts(INT_CCP1);
  35.         //enable_interrupts(INT_TIMER0);
  36.         enable_interrupts(INT_TIMER1);
  37.         //enable_interrupts(INT_TIMER2);
  38.         enable_interrupts(GLOBAL);
  39.         setup_oscillator(OSC_4MHZ);
  40.        
  41.         CCP_1 = 55574;
  42.         set_timer1(65533);
  43.         //set_timer0(254);
  44.         //set_timer2(254);
  45.         delay_cycles(1);
  46.         delay_cycles(1);
  47.         delay_cycles(1);
  48.         delay_cycles(1);
  49.         do{                    
  50.  
  51.         }while(TRUE);  
  52. }

El codigo ASM equivalente es:

Código: ASM
  1. 1:                 #include <12F683.h>
  2.    000    3000     MOVLW 0
  3.    001    008A     MOVWF 0xa
  4.    002    285F     GOTO 0x5f
  5.    003    0000     NOP
  6.    004    1A83     BTFSC 0x3, 0x5
  7.    005    280A     GOTO 0xa
  8.    006    00A5     MOVWF 0x25
  9.    007    0E03     SWAPF 0x3, W
  10.    008    00A6     MOVWF 0x26
  11.    009    280F     GOTO 0xf
  12.    00A    1283     BCF 0x3, 0x5
  13.    00B    00A5     MOVWF 0x25
  14.    00C    0E03     SWAPF 0x3, W
  15.    00D    00A6     MOVWF 0x26
  16.    00E    14A6     BSF 0x26, 0x1
  17.    00F    080A     MOVF 0xa, W
  18.    010    00AD     MOVWF 0x2d
  19.    011    018A     CLRF 0xa
  20.    012    1383     BCF 0x3, 0x7
  21.    013    0EA5     SWAPF 0x25, F
  22.    014    0804     MOVF 0x4, W
  23.    015    00A7     MOVWF 0x27
  24.    016    0820     MOVF 0x20, W
  25.    017    00A8     MOVWF 0x28
  26.    018    0821     MOVF 0x21, W
  27.    019    00A9     MOVWF 0x29
  28.    01A    0822     MOVF 0x22, W
  29.    01B    00AA     MOVWF 0x2a
  30.    01C    0823     MOVF 0x23, W
  31.    01D    00AB     MOVWF 0x2b
  32.    01E    0824     MOVF 0x24, W
  33.    01F    00AC     MOVWF 0x2c
  34.    020    1283     BCF 0x3, 0x5
  35.    021    308C     MOVLW 0x8c
  36.    022    0084     MOVWF 0x4
  37.    023    1C00     BTFSS 0, 0
  38.    024    2827     GOTO 0x27
  39.    025    180C     BTFSC 0xc, 0
  40.    026    2850     GOTO 0x50
  41.    027    308C     MOVLW 0x8c
  42.    028    0084     MOVWF 0x4
  43.    029    1C80     BTFSS 0, 0x1
  44.    02A    282D     GOTO 0x2d
  45.    02B    188C     BTFSC 0xc, 0x1
  46.    02C    2857     GOTO 0x57
  47.    02D    1E8B     BTFSS 0xb, 0x5
  48.    02E    2831     GOTO 0x31
  49.    02F    190B     BTFSC 0xb, 0x2
  50.    030    284C     GOTO 0x4c
  51.    031    308C     MOVLW 0x8c
  52.    032    0084     MOVWF 0x4
  53.    033    1E80     BTFSS 0, 0x5
  54.    034    2837     GOTO 0x37
  55.    035    1A8C     BTFSC 0xc, 0x5
  56.    036    285B     GOTO 0x5b
  57.    037    0827     MOVF 0x27, W
  58.    038    0084     MOVWF 0x4
  59.    039    0828     MOVF 0x28, W
  60.    03A    00A0     MOVWF 0x20
  61.    03B    0829     MOVF 0x29, W
  62.    03C    00A1     MOVWF 0x21
  63.    03D    082A     MOVF 0x2a, W
  64.    03E    00A2     MOVWF 0x22
  65.    03F    082B     MOVF 0x2b, W
  66.    040    00A3     MOVWF 0x23
  67.    041    082C     MOVF 0x2c, W
  68.    042    00A4     MOVWF 0x24
  69.    043    082D     MOVF 0x2d, W
  70.    044    008A     MOVWF 0xa
  71.    045    0E26     SWAPF 0x26, W
  72.    046    0083     MOVWF 0x3
  73.    047    1283     BCF 0x3, 0x5
  74.    048    0E25     SWAPF 0x25, W
  75.    049    18A6     BTFSC 0x26, 0x1
  76.    04A    1683     BSF 0x3, 0x5
  77.    04B    0009     RETFIE
  78. 2:                 #device adc=8
  79. 3:                
  80. 4:                 #FUSES NOWDT,NOMCLR,PUT,INTRC_IO
  81. 5:                 #use delay(clock=4000000)
  82. 6:                
  83. 7:                 #int_TIMER0
  84. 8:                 void TIMER0_isr(void) {
  85. 9:                      delay_cycles(1);
  86.    04C    0000     NOP
  87. 10:                }
  88.    04D    110B     BCF 0xb, 0x2
  89.    04E    118A     BCF 0xa, 0x3
  90.    04F    2837     GOTO 0x37
  91. 11:                #int_TIMER1
  92. 12:                void TIMER1_isr(void) {
  93. 13:                     //delay_cycles(1);
  94. 14:                     set_timer1(45574);
  95.    050    30B2     MOVLW 0xb2
  96.    051    008F     MOVWF 0xf
  97.    052    3006     MOVLW 0x6
  98.    053    008E     MOVWF 0xe
  99. 15:                }
  100.    054    100C     BCF 0xc, 0
  101.    055    118A     BCF 0xa, 0x3
  102.    056    2837     GOTO 0x37
  103. 16:                #int_TIMER2
  104. 17:                void TIMER2_isr(void) {
  105. 18:                     delay_cycles(1);
  106.    057    0000     NOP
  107. 19:                }
  108.    058    108C     BCF 0xc, 0x1
  109.    059    118A     BCF 0xa, 0x3
  110.    05A    2837     GOTO 0x37
  111. 20:                #int_CCP1
  112. 21:                void CCP1_isr(void){
  113. 22:                     delay_cycles(1);
  114.    05B    0000     NOP
  115. 23:                }
  116.    05C    128C     BCF 0xc, 0x5
  117.    05D    118A     BCF 0xa, 0x3
  118.    05E    2837     GOTO 0x37
  119. 24:                void main() {
  120.    05F    0184     CLRF 0x4
  121.    060    301F     MOVLW 0x1f
  122.    061    0583     ANDWF 0x3, F
  123.    062    3061     MOVLW 0x61
  124.    063    1683     BSF 0x3, 0x5
  125.    064    008F     MOVWF 0xf
  126.    065    1283     BCF 0x3, 0x5
  127.    066    131F     BCF 0x1f, 0x6
  128.    067    1683     BSF 0x3, 0x5
  129.    068    101F     BCF 0x1f, 0
  130.    069    109F     BCF 0x1f, 0x1
  131.    06A    111F     BCF 0x1f, 0x2
  132.    06B    119F     BCF 0x1f, 0x3
  133.    06C    3007     MOVLW 0x7
  134.    06D    1283     BCF 0x3, 0x5
  135.    06E    0099     MOVWF 0x19
  136. 25:                    
  137. 26:                     setup_adc_ports(NO_ANALOGS|VSS_VDD);
  138.    06F    131F     BCF 0x1f, 0x6
  139.    070    1683     BSF 0x3, 0x5
  140.    071    101F     BCF 0x1f, 0
  141.    072    109F     BCF 0x1f, 0x1
  142.    073    111F     BCF 0x1f, 0x2
  143.    074    119F     BCF 0x1f, 0x3
  144. 27:                     setup_adc(ADC_CLOCK_INTERNAL);
  145.    075    161F     BSF 0x1f, 0x4
  146.    076    169F     BSF 0x1f, 0x5
  147.    077    131F     BCF 0x1f, 0x6
  148.    078    1283     BCF 0x3, 0x5
  149.    079    139F     BCF 0x1f, 0x7
  150.    07A    141F     BSF 0x1f, 0
  151. 28:                     setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
  152.    07B    1683     BSF 0x3, 0x5
  153.    07C    0801     MOVF 0x1, W
  154.    07D    39C7     ANDLW 0xc7
  155.    07E    3808     IORLW 0x8
  156.    07F    0081     MOVWF 0x1
  157. 29:                     setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
  158.    080    3085     MOVLW 0x85
  159.    081    1283     BCF 0x3, 0x5
  160.    082    0090     MOVWF 0x10
  161. 30:                     setup_timer_2(T2_DIV_BY_1,255,1);
  162.    083    3000     MOVLW 0
  163.    084    00A1     MOVWF 0x21
  164.    085    3804     IORLW 0x4
  165.    086    0092     MOVWF 0x12
  166.    087    30FF     MOVLW 0xff
  167.    088    1683     BSF 0x3, 0x5
  168.    089    0092     MOVWF 0x12
  169. 31:                     setup_ccp1(CCP_COMPARE_INT);
  170.    08A    1505     BSF 0x5, 0x2
  171.    08B    300A     MOVLW 0xa
  172.    08C    1283     BCF 0x3, 0x5
  173.    08D    0095     MOVWF 0x15
  174. 32:                     setup_comparator(NC_NC);
  175.    08E    3007     MOVLW 0x7
  176.    08F    0099     MOVWF 0x19
  177.    090    1683     BSF 0x3, 0x5
  178.    091    0805     MOVF 0x5, W
  179.    092    3003     MOVLW 0x3
  180.    093    1283     BCF 0x3, 0x5
  181.    094    00A0     MOVWF 0x20
  182.    095    0BA0     DECFSZ 0x20, F
  183.    096    2895     GOTO 0x95
  184.    097    0819     MOVF 0x19, W
  185.    098    118C     BCF 0xc, 0x3
  186. 33:                     setup_vref(FALSE);
  187.    099    1683     BSF 0x3, 0x5
  188.    09A    0199     CLRF 0x19
  189. 34:                     //enable_interrupts(INT_CCP1);
  190. 35:                     //enable_interrupts(INT_TIMER0);
  191. 36:                     enable_interrupts(INT_TIMER1);
  192.    09B    140C     BSF 0xc, 0
  193. 37:                     //enable_interrupts(INT_TIMER2);
  194. 38:                     enable_interrupts(GLOBAL);
  195.    09C    30C0     MOVLW 0xc0
  196.    09D    1283     BCF 0x3, 0x5
  197.    09E    048B     IORWF 0xb, F
  198. 39:                     setup_oscillator(OSC_4MHZ);
  199.    09F    3061     MOVLW 0x61
  200.    0A0    1683     BSF 0x3, 0x5
  201.    0A1    008F     MOVWF 0xf
  202. 40:                    
  203. 41:                     CCP_1 = 55574;
  204.    0A2    30D9     MOVLW 0xd9
  205.    0A3    1283     BCF 0x3, 0x5
  206.    0A4    0094     MOVWF 0x14
  207.    0A5    3016     MOVLW 0x16
  208.    0A6    0093     MOVWF 0x13
  209. 42:                     set_timer1(65533);
  210.    0A7    30FF     MOVLW 0xff
  211.    0A8    008F     MOVWF 0xf
  212.    0A9    30FD     MOVLW 0xfd
  213.    0AA    008E     MOVWF 0xe
  214. 43:                     //set_timer0(254);
  215. 44:                     //set_timer2(254);
  216. 45:                     delay_cycles(1);
  217.    0AB    0000     NOP
  218. 46:                     delay_cycles(1);
  219.    0AC    0000     NOP
  220. 47:                     delay_cycles(1);
  221.    0AD    0000     NOP
  222. 48:                     delay_cycles(1);
  223.    0AE    0000     NOP
  224. 49:                     do{                    
  225. 50:                
  226. 51:                     }while(TRUE);  
  227.    0AF    28AF     GOTO 0xaf
  228.    0B0    0063     SLEEP

Lo realmente interesante va de la linea 4  hasta el RETFIE de la linea 4B, que salva el contexto, elige la interrupcion y luego devuelve el contexto.
En resumen, para que no tengais que analizar todo el codigo:
  • Linea 4 a D: pasa a la pagina 0 si es necesario y guarda W y Status
  • Linea E a 1F: guarda el estado actual del PIC
  • Linea 21 a 36: comprueba que interrupcion atender
  • Linea 37 a 4B: restaura valores de antes de la interrupcion y sale de ella

basicamente quisiera meter algunos NOP para que sea cual sea la interrupcion que hay que atender, y el estado del pic, se tarde lo mismo siempre en entrar o salir de cualquiera de las interrupciones.
Hay alguna manera de hacerlo sin tener que editar TODO el codigo en ASM como cuenta el amigo jacrmr?

Tambien hay un par de cosillas que no me cuadran:
*Porque al guardar STATUS en la linea 7 y linea C se hace un swap a los bits, y luego se hace otro swap al devolverlos en la linea 45? Para que el swap?
*Porque se devuelve el contenido de W con un swap en la linea 48 si al guardarlo no se le hizo swap?
*Al salvar el contexto (de E a 1F) se guardan los valores de 0x20 hasta 0x24. 0x20 se utiliza en la linea 94, 0x21 se usa en la linea 84. El resto para que se guardan? no veo que se utilicen para nada  :?  Serian unos cuantos ciclos que me ahorro a la entrada y salida de las interrupciones.

Bueno, gracias a todos por la ayuda. Esto de ASM me esta gustando  :-)  aunque no tanto como para hacer todo el programa con el  :P
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 PalitroqueZ

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5490
    • Electrónica Didacta
Re: Entrar a interrupcion en ASM, en entorno C
« Respuesta #4 en: 04 de Noviembre de 2008, 14:45:20 »
....basicamente quisiera meter algunos NOP para que sea cual sea la interrupcion que hay que atender, y el estado del pic, se tarde lo mismo siempre en entrar o salir de cualquiera de las interrupciones.
Hay alguna manera de hacerlo sin tener que editar TODO el codigo en ASM como cuenta el amigo jacrmr?

...

claro que si la hay, pero es algo que no tiene que ver con el lenguaje, sino con los ensayos fisicos.

1.- Podrias usar el mplab-sim y colocar un breakpoints en sitios estrategicos y medir el tiempo transcurrido y en base a esto, ajustar con delay_cycles(n) hasta completar el tiempo

1.1- En ccs es imposible medir el tiempo con precisión, porque el compilador mete unas lineas adicionales (transparentes al usuario) para hacer otros calculos, eso creo que lo llaman stack frame.

Así escribas un nop en main igual te escribe un encabezado por defecto

2.- podrias usar un osciloscopio y con togglear un pin, podrias medir el tiempo transcurrido con mayor precisión.

La propiedad privada es la mayor garantía de libertad.
Friedrich August von Hayek

Desconectado Giovanny

  • PIC12
  • **
  • Mensajes: 97
    • Supercomponentes
Re: Entrar a interrupcion en ASM, en entorno C
« Respuesta #5 en: 04 de Noviembre de 2008, 15:25:01 »
TOMADO DE LA AYUDA DE CCS
--------------------------------------------------------------------------------
#ASM
#ENDASM

--------------------------------------------------------------------------------
Syntax:
 #asm
   or
#asm ASIS
   code
 #endasm
 
Elements:
 code is a list of assembly language instructions
 
Purpose:
 The lines between the #ASM and #ENDASM are treated as assembly code to be inserted.    These may be used anywhere an expression is allowed.   The syntax is described on the following page.   The predefined variable _RETURN_ may be used to assign a return value to a function from the assembly code.    Be aware that any C code after the #ENDASM and before the end of the function may corrupt the value.

 If the second form is used with ASIS then the compiler will not do any automatic bank switching for variables that cannot be accessed from the current bank.  The assembly code is used as-is.  Without this option the assembly is augmented so variables are always accessed correctly by adding bank switching where needed.
 
Examples:

Código: [Seleccionar]
int find_parity (int data)    {

int count;
#asm
movlw   0x8
movwf   count
movlw   0
loop:
xorwf   data,w
rrf     data,f
decfsz  count,f
goto    loop
movlw   1
awdwf   count,f
movwf   _return_
#endasm
}
        Saludos desde Colombia! Que hermoso país....

Desconectado MLO__

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4581
Re: Entrar a interrupcion en ASM, en entorno C
« Respuesta #6 en: 04 de Noviembre de 2008, 17:57:59 »
Hola.

Para que funcione lo de la ayuda hay que hacer el direccionamiento de los registros con #byte y #bit. Sin embargo a mi no me ha funcionado bien que digamos ....

Saludos
El papel lo aguanta todo

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: Entrar a interrupcion en ASM, en entorno C
« Respuesta #7 en: 04 de Noviembre de 2008, 18:30:36 »
Hola Marttyn

*Porque al guardar STATUS en la linea 7 y linea C se hace un swap a los bits, y luego se hace otro swap al devolverlos en la linea 45? Para que el swap?

Porque la instrucción swapf no afecta ningún flag del registro STATUS.

*Porque se devuelve el contenido de W con un swap en la linea 48 si al guardarlo no se le hizo swap?

Porque para guardarlo sólo se debe hacer movwf registro_aux(que no afecta ningún flag del STATUS), pero si quisieras restaurarlo haciendo, por ejemplo, movf registro_aux,w esto afecta al flag Z del registro STATUS y no es lo correcto. Por eso se utilizan los SWAPF para restaurar los registros.

*Al salvar el contexto (de E a 1F) se guardan los valores de 0x20 hasta 0x24. 0x20 se utiliza en la linea 94, 0x21 se usa en la linea 84. El resto para que se guardan? no veo que se utilicen para nada  Confused  Serian unos cuantos ciclos que me ahorro a la entrada y salida de las interrupciones.

Probablemente el Compilador reserve por defecto esas posiciones de memoria para ciertos módulos o funciones especiales.

En cuanto a la inyección de NOPs, creo que vas a tener que hacerlo desde el código ASM de salida, porque no creo que haya lugar para poder inyectarlos dentro de la ISR desde el compilador. No va a ser tarea fácil, por ahí como te han recomendado con el MPLAB SIM lo hagas mucho más rápido.

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 #8 en: 05 de Noviembre de 2008, 04:36:59 »
Hola a todos!
Gracias por vuestros comentarios!

Pali:
Efectivamente estoy usando el Stopwatch, y analizando el codigo directamente en ASM desde el MPLAB.

Giovanny:
Conozco lo de #asm para insertar codigo ASM entre medio del codigo C, pero el problema es que quiero insertar ASM en lugares donde el codigo C no llega, esas lineas transparentes al usuario que habla palitroquez.

BrunoF:
*Porque al guardar STATUS en la linea 7 y linea C se hace un swap a los bits, y luego se hace otro swap al devolverlos en la linea 45? Para que el swap?

Porque la instrucción swapf no afecta ningún flag del registro STATUS.

y en vez de usar la instruccion SWAPF, no se podria usar la instruccion MOVELW? Tampoco afecta al registro Z.

Citar
*Porque se devuelve el contenido de W con un swap en la linea 48 si al guardarlo no se le hizo swap?

Porque para guardarlo sólo se debe hacer movwf registro_aux(que no afecta ningún flag del STATUS), pero si quisieras restaurarlo haciendo, por ejemplo, movf registro_aux,w esto afecta al flag Z del registro STATUS y no es lo correcto. Por eso se utilizan los SWAPF para restaurar los registros.

Ok, no me habia dado cuenta que al guardar NO hace SWAP, pero lo hace unas instrucciones mas adelante sobre el valor guardado, por eso al recuperar el contexto le vuelve a hacer el SWAP.
Aun asi sigo sin entender que importancia tiene modificar el registro Z, en realidad al guardar los registros del 0x20 al 0x24 lo hace con MOVF y MOVWF, con lo que estan modificando Z.

Citar
*Al salvar el contexto (de E a 1F) se guardan los valores de 0x20 hasta 0x24. 0x20 se utiliza en la linea 94, 0x21 se usa en la linea 84. El resto para que se guardan? no veo que se utilicen para nada  Confused  Serian unos cuantos ciclos que me ahorro a la entrada y salida de las interrupciones.

Probablemente el Compilador reserve por defecto esas posiciones de memoria para ciertos módulos o funciones especiales.

Si mi programa no usa esas posiciones de memoria, puedo omitir salvar el contexto de dichas posiciones, y tambien omitir restaurarlas? Me ahorro 10 instrucciones en la entrada y otras 10 en la salida de la interrupcion!

Citar
En cuanto a la inyección de NOPs, creo que vas a tener que hacerlo desde el código ASM de salida, porque no creo que haya lugar para poder inyectarlos dentro de la ISR desde el compilador. No va a ser tarea fácil, por ahí como te han recomendado con el MPLAB SIM lo hagas mucho más rápido.

Como le dije a pali, estoy usando MPLAB para hacer todo esto, escribo el codigo en C, y al compilarlo debuggeo el ASM que genera. Entonces tendre que modificar ese ASM generado, no? No puedo hacer los cambios directamente desde C supongo...  :?

Sigo mirando el codigo y hay otras cosas que no entiendo....
*Por que en la linea 20 da la instruccion de pasar al Register Bank 0, si ya comprueba que esta en el banco 0 en la linea 4, y desde entonces no hay ninguna instruccion que cambie de banco. ¿?
*En la linea 12 pone a 0 el bit IRP de Status. Pero en el datasheet dice que no toquemos ese bit. Para que sirve?
*No entiendo muy bien que funcion cumplen las lineas 23 y 29? Segun el datasheet leer indirectamente el registro INDF devolvera 00h... ¿leer indirectamente?

Lamento tantas preguntas, tal vez deberia dirigirme al foro de ASM para resolverlas...
Un saludo y gracias a todos!
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 #9 en: 05 de Noviembre de 2008, 06:14:44 »
Hola!

y en vez de usar la instruccion SWAPF, no se podria usar la instruccion MOVELW? Tampoco afecta al registro Z.

Supongo que te referirás a la instrucción MOVLW. No es posible. 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).

Ok, no me habia dado cuenta que al guardar NO hace SWAP, pero lo hace unas instrucciones mas adelante sobre el valor guardado, por eso al recuperar el contexto le vuelve a hacer el SWAP.
Aun asi sigo sin entender que importancia tiene modificar el registro Z, en realidad al guardar los registros del 0x20 al 0x24 lo hace con MOVF y MOVWF, con lo que estan modificando Z.

Lo importante no es NO modificarlo. Lo importante es no modificarlo mientras lo guardás o lo restaurás. Es decir, los registros clave deben valer al retornar de la interr. exáctamente lo mísmo que valían antes de ingresar a la ISR.

Si mi programa no usa esas posiciones de memoria, puedo omitir salvar el contexto de dichas posiciones, y tambien omitir restaurarlas? Me ahorro 10 instrucciones en la entrada y otras 10 en la salida de la interrupcion!

Podés. Siempre y cuando el programa no las use, volalas tranquilo.

Como le dije a pali, estoy usando MPLAB para hacer todo esto, escribo el codigo en C, y al compilarlo debuggeo el ASM que genera. Entonces tendre que modificar ese ASM generado, no? No puedo hacer los cambios directamente desde C supongo...  :?
Y..no veo otra manera, al menos desde lo que conozco. El problema es que no exíste una función en C referida a la ISR como para que puedas al menos inyectar los NOP desde código C. Tal vez usando el #asm y el org 0xXXX puedas hacer algo desde C pero no se si no te pisarás con el compilador...

Sigo mirando el codigo y hay otras cosas que no entiendo....
*Por que en la linea 20 da la instruccion de pasar al Register Bank 0, si ya comprueba que esta en el banco 0 en la linea 4, y desde entonces no hay ninguna instruccion que cambie de banco. ¿?

Está de mas. Podés sacarla tranquilo. Es mas: hay varias que se podrían unir y hacer el código más corto por lo que veo...

*En la linea 12 pone a 0 el bit IRP de Status. Pero en el datasheet dice que no toquemos ese bit. Para que sirve?

El bit IRP sirve sólo en uC que poseen más de 256 registros RAM. Sirve para acceder a los registros superiores de la RAM mediante direccionamiento indirecto(registros FSR e INDF). Como este uC que estás usando no posee más de 256 registros, no deberías tocarlo. Conclusión. Podés eliminar esa línea también.

*No entiendo muy bien que funcion cumplen las lineas 23 y 29? Segun el datasheet leer indirectamente el registro INDF devolvera 00h... ¿leer indirectamente?

Para comprenderlas, debés aprender sobre el direccionamiento indirecto y las lineas previas a las que desconocés su función.

  ...
  021    308C     MOVLW 0x8c
  022    0084     MOVWF 0x4
  023    1C00     BTFSS 0, 0
  024    2827     GOTO 0x27
  025    180C     BTFSC 0xc, 0
  026    2850     GOTO 0x50
  027    308C     MOVLW 0x8c
  028    0084     MOVWF 0x4
  029    1C80     BTFSS 0, 0x1
  ...
Se transforma directamente(con palabras un poco más legibles) en:

  ...
  021    308C     MOVLW PIE1
  022    0084     MOVWF FSR
  023    1C00     BTFSS INDF, 0
  024    2827     GOTO 0x27
  025    180C     BTFSC PIR1, TMR1IF
  026    2850     GOTO 0x50
  027    308C     MOVLW PIE1
  028    0084     MOVWF FSR
  029    1C80     BTFSS INDF,1
  ...

Y ahora yo la paso de assembler a español :mrgreen: :mrgreen: :mrgreen: :mrgreen:


  021    308C     MOVLW PIE1    ;(Cargo en W la dirección a la cual quiero acceder de manera indirecta...es decir, 0x8C)
  022    0084     MOVWF FSR      ;(la copio al registro FSR. Entonces, ahora al leer INDF, hacé de cuenta que estoy leyendo en realidad el registro 0x8C. Esto es básicamente el direccionamiento indirecto)
  023    1C00     BTFSS INDF, 0  ;(esto sería como hacer entonces... btfss PIE1,TMR1IE) = Interrupción de timer1 habilitada?
  024    2827     GOTO 0x27       ;no, ir a 0x27
  025    180C     BTFSC PIR1, TMR1IF ;Si. Ahora, btfsc PIR1,TMR1IF) = La bandera de interrupción del timer1 NO se ha producido?
  026    2850     GOTO 0x50       ;Se ha producido, ir a 0x50
  027    308C     MOVLW PIE1     ;No. El timer1 no ha interrumpido. Mover nuevamente el valor 0x8C a W
  028    0084     MOVWF FSR       ;y nuevamente apunta rindirectamente a él(estas dos podrías sacarse creo)
  029    1C80     BTFSS INDF,1    ;(esto sería como hacer entonces... btfss PIE1,TMR2IE) = Interrupción de timer2 habilitada?
  ...

Y sigue..

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 BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: Entrar a interrupcion en ASM, en entorno C
« Respuesta #10 en: 05 de Noviembre de 2008, 06:17:23 »
Comentario al margen:

Cuanto más mires el código ASM de salida generado de un compilador, más ganas te van a dar ganas de pasarte a ASM si necesitás controlar los tiempos a la perfección. Esa rutina de interrupción deja bastante que desear...

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 PalitroqueZ

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5490
    • Electrónica Didacta
Re: Entrar a interrupcion en ASM, en entorno C
« Respuesta #11 en: 05 de Noviembre de 2008, 15:53:05 »
Comentario al margen:

Cuanto más mires el código ASM de salida generado de un compilador, más ganas te van a dar ganas de pasarte a ASM si necesitás controlar los tiempos a la perfección. Esa rutina de interrupción deja bastante que desear...

Saludos.

si eso es cierto, yo tengo un proyecto estancado, porque me impuse la manía de simplificar el asm generado por el C, casi que mando ese proyecto a freir monos.


Cuando se programa en C, hay que olvidarse un poco de la velocidad y subir la potencia del pic.

La propiedad privada es la mayor garantía de libertad.
Friedrich August von Hayek

Desconectado Leon Pic

  • Colaborador
  • DsPIC30
  • *****
  • Mensajes: 3610
    • Impresiones en 3D
Re: Entrar a interrupcion en ASM, en entorno C
« Respuesta #12 en: 05 de Noviembre de 2008, 17:47:52 »
El lenguaje C, no es más que subrutinas para cada instrucción del CCS. Es por eso que pone el banco 0 otra vez. Ya que, en la rutina que tiene grabada, empieza poniendo el banco 0 por si antes se ejecutó otra rutina y lo dejó en cualquier banco.

Todo el lenguaje C, son rutinas pregrabadas que se iran uniendo según se valla escribiendo el programa. Al tener rutina pre grabadas, hace que la programación sea más fácil pero sacrificando instrucciones de más y tiempo demás. Lo mismo ocurre en ASM. Yo puedo crear carios tipos de rutinas en librerías y luego ir incluyendola, pero si quiero una buena programación, voy a tener que estar modificando las librerías antes mencionadas.

Además, cada subrutina grabada es generalizada para varios tipos de pic, de esta manera no se hace una subrutina para cada tipo de pic.
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 #13 en: 06 de Noviembre de 2008, 02:17:04 »
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:

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?
Si uso direccionamiento indirecto, en FSR tengo el PORTA por ej, cuando cambie el PORTA, tambien cambiara FSR?
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 ¿?


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, llevo un par de dias con ASM y la verdad se pone cada vez mas interesante... Y como estan diciendo TODOS, hay que cambiarse a ASM si quiero tener control total sobre las instrucciones. Mucha razon tienen, pero por ahora lo unico que me da problemas es el ISR, asi que escribire el codigo en C, y modificare el ASM generado. Aun no tengo conocimientos como para hacer todo el programa en ASM.

Pali, lo que no veo muy logico es pasarse a un micro mas potente y quedarse en C. Si tu programa necesita precision de instrucciones, por mas que te pases a un micro mas rapido, las instrucciones que genera "de mas" el CCS, y las rutinas poco eficientes siguen estando ahi, y aunque se ejecuten mas rapido, sigues teniendo una imprecision que no puedes controlar.

Creo que va siendo hora que me busque un manual de ASM, porque aprender del datasheet del PIC y del codigo generado de mi programa esta dejandome con demasiadas dudas  :-)
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 #14 en: 06 de Noviembre de 2008, 02:36:28 »
Citar
*El direccionamiento indirecto que funcion tiene? Si podemos leer el registro directamente, para que lo vamos a leer de manera indirecta?

Precisamente su función e importancia es el no tener que hacerlo directamente, aunque parezca algo confuso. Si quieres abordar un autobús en la central de autobuses es más lógico y práctico que vayas al tablero de salidas (direccionamiento indirecto) y conozcas la hora de salida de tu autobús, que ir directamente con el piloto o chofer del mismo a preguntarle a él (que además no te lo permitirían tal vez).

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.