Autor Tema: Interruciones  (Leído 5082 veces)

Dr.Fred

  • Commodoremaníaco
  • ****
  • Mensajes: 144
    • Ver Perfil
Interruciones
« en: Marzo 08, 2011, 23:09:42 »
Hola!
Hacía mucho que no escribía, aunque os leo muy a menudo y me alegra ver que paso a paso se van gestando cosas por aquí. Un saludo a todos.

Este año he empezado un ciclo de electrónica y para mi sorpresa, en la asignatura de Electrónica Digital, nos estamos centrando en el procesador 6502 (Imaginaos el subidón que me dio al saberlo), así que estoy aprendiendo ensamblador y disfrutando como un enano.

Por mi cuenta he empezado a ver el tema de interrupciones y he leído algunos libros respecto al tema, pero hay cosas que no me quedan claras.

Si no he entendido mal, a grandes rasgos, consiste en dos bytes que contienen el puntero a la dirección de memoria que se ejecutará cuando se realice la interrución. Cuando salte una interrupcion, el sistema irá a esta zona y ejecutará lo que haya de modo similar a si fuera una subrutina.

Mi primera pregunta es: ¿Cuando y cómo se llama a una interrupción?

También he leído que el sistema utiliza las interrupciones 60 veces por segundo (controlar el reloj, controlar la entrada de teclado, flasheo del cursor, etc...) Entonces supongo que esos dos bytes de puntero cambian en la memoria muchísimas veces ( de ahí la necesidad de usar la instrucción SEI) La cuestión es: cuando yo le meta a esas direcciones una dirección de mi rutina, entiendo que se machacará seguidamente por la que quiera usar el sistema. Entonces, si yo quisiera ejecutar esa rutina varias veces, ¿qué tendría que hacer?

A ver si alguien me puede aclarar un poco este tema, que en los libros no lo veo muy claro y tampoco encuentro muchos ejemplos que lo expliquen.

Os pongo un ejemplo de una interrupción que lee el teclado y escribe en pantalla. Lo que no consigo entender es en qué parte se llama a la interrupción en el programa... o simplemente poniendo la dirección en los dos bytes, ejecutaría mi interrupción... pero sólo lo haría una vez, porque se queda en un bucle infinito en la etiqueta HERE...  No sé... hay algo que no termino de ver.



Bueno, muchas gracias por adelantado.

[code]
MAIN    SEI
      LDA #00
      STA USRVTR
      LDA #$C1
      STA USRVTR+1
      CLI
HERE   JMP HERE


      EQU $C100
IRQ      JSR SCNKEY
      LDX +$C6
      BEQ OUT
      DEX
      STX +$C6
      LDA $0277
      JSR CHROUT
OUT      LDA IRQCTL
      PLA
      TAY
      PLA
      TAX
      PLA
      RTI
[/quote]

Carlos

  • Desarrolladores
  • Commodore Master
  • ******
  • Mensajes: 652
    • Ver Perfil
Interruciones
« Respuesta #1 en: Marzo 08, 2011, 23:50:36 »
Pásate por RetroEncounter y te lo explico  :wink:

PD: Cuando tenga un rato también te lo intento explicar por el foro.

Dr.Fred

  • Commodoremaníaco
  • ****
  • Mensajes: 144
    • Ver Perfil
Interruciones
« Respuesta #2 en: Marzo 09, 2011, 09:13:21 »
Que me voy a pasar por ahí es un hecho... sería pecado perderselo. Pero... aun queda mucho tiempo y mi hambre de ensamblador es insaciable!! Jeje, no, fuera coña. Te agradecería mucho si pudieras darme alguna pista cuando tengas tiempo. Un saludo!

Carlos

  • Desarrolladores
  • Commodore Master
  • ******
  • Mensajes: 652
    • Ver Perfil
Interruciones
« Respuesta #3 en: Marzo 09, 2011, 14:18:23 »
Citar
Por mi cuenta he empezado a ver el tema de interrupciones y he leído algunos libros respecto al tema, pero hay cosas que no me quedan claras.


Te lo intentaré ir respondiendo en píldoras por falta de tiempo...

Citar
Si no he entendido mal, a grandes rasgos, consiste en dos bytes que contienen el puntero a la dirección de memoria que se ejecutará cuando se realice la interrución. Cuando salte una interrupcion, el sistema irá a esta zona y ejecutará lo que haya de modo similar a si fuera una subrutina.


Antes de nada aclarar que tipos de interrupciones hay varios: raster, NMI, las producidas por las CIAs, y no sé si alguna mas.

Básicamente el funcionamiento es el que dices (al menos en el caso de las interrupciones raster que son las que conozco), digamos que se interrumpe el flujo de instrucciones normal del procesador para 'saltar' a esa dirección donde está el código que se ejecuta.

Citar
Mi primera pregunta es: ¿Cuando y cómo se llama a una interrupción?


En el caso de las raster (repito que es el caso que conozco) se llama cuando nosotros se lo indicamos, es decir, en cada refresco de pantalla (que se hace 50 veces por segundo = 50 Hz en sistemas PAL) nosotros le podemos indicar al procesador que se ejecute una interrupción en una o varias de las diferentes líneas (o rasters) de la pantalla.

Esto lo haríamos modificando el registro $d012, el valor que pongamos en él indicará en que número de línea de pantalla 'saltará' la próxima interrupción raster.

josepzin

  • Administrador
  • Commodore Master
  • *****
  • Mensajes: 13630
  • Commodoreador web
    • Ver Perfil
    • Mi blog
Interruciones
« Respuesta #4 en: Marzo 11, 2011, 00:53:25 »
Dr.Fred: que bueno!!
www.retroinvaders.com | www.commodoreplus.org  | josepzin.blogspot.com

lobogris

  • Desarrolladores
  • Commodore Master
  • ******
  • Mensajes: 453
  • Programador
    • Ver Perfil
    • http://back2theretro.blogspot.com
Re: Interruciones
« Respuesta #5 en: Marzo 11, 2011, 16:44:14 »
Cita de: "Dr.Fred"

Mi primera pregunta es: ¿Cuando y cómo se llama a una interrupción?

También he leído que el sistema utiliza las interrupciones 60 veces por segundo (controlar el reloj, controlar la entrada de teclado, flasheo del cursor, etc...) Entonces supongo que esos dos bytes de puntero cambian en la memoria muchísimas veces ( de ahí la necesidad de usar la instrucción SEI) La cuestión es: cuando yo le meta a esas direcciones una dirección de mi rutina, entiendo que se machacará seguidamente por la que quiera usar el sistema. Entonces, si yo quisiera ejecutar esa rutina varias veces, ¿qué tendría que hacer?


Empiezo por el final (como los japoneses que leen desde la ultima página hacia la primera jaja):

Cuando quieras usar tu propia rutina, es buena idea devolver el control a la rutina que se ejecutaba antes de modificar el vector, simplemente con un JMP al final de la tuya.


Las interrupciones no las llama un programa, las llama continuamente la CPU, y como bien dice Carlos, hay varios tipos de interrupciones. Unas (las raster por ejemplo) las llama el chip Vic-II (el encargado del apartado gráficos).

Cada cierto tiempo (60 veces por segundo en sistemas NTSC o 50 en PAL) la cpu salta al fragmento de código especificado en su correspondiente "vector de interrupcion" (ese par de  bytes que indican una direccion de los que hablabas)
y lo ejecuta. Pero antes guarda el estado de todos los registros en la pila incluyendo la direccion del PC(puntero de programa) actual antes de iniciar la interrupción, para cuando regrese al programa que se estaba ejecutando, todo este proceso haya sido totalmente "transparente". Es importantísimo saber que las rutinas que se ejecuten por la interrupcion de cada tipo de interrupcion son responsables de recuperar la pila.

Hay interrupciones enmmascarables (IRQ) o no enmascarables (NMI). Las enmascarables, son las que pueden ser ignoradas (tocando un bit usando una mascara de bits, de ahi su nombre), las NMI, no tienen una mascara de bits asociada para tocar, por lo que no pueden ser ignoradas (siempre serán llamadas: otra cosa es que apuntemos a una rutina "vacia", por ejemplo).

Tambien está el tipo de interrupción por software, que es una que no se llama automáticamente por la cpu, si no que es un programa la que la genera, y se hace mediante la instrucción BRK o pulsando RUN-STOP/RESTORE

En resumen, solo hay una interrupción (las de software) que podremos "llamarla" nosotros, las otras, son continuamente llamadas por el propio sistema.

En general, además, tal como viene el sistema al encenderlo, el vector de interrupción de cada interrupción están inmutables, no cambian cada vez que tiene que hacer una tarea, en realidad, una interrupción por ejemplo, comprueba el reloj y hace parpadear el cursor en el mismo fragmento de código, y otras tareas las hace otra interrupción, como por ejemplo gestionar el teclado...

En nuestros programas, si que podemos cambiar muchas veces ese vector para hacer cosas como múltiples interrupciones pero no es aconsejable más de dos, por que restan ciclos tambien de la CPU.

Tambien se pueden programar la frecuencia a la que las interrupciones serán ejecutadas, con el raster, o con los timers.

lobogris

  • Desarrolladores
  • Commodore Master
  • ******
  • Mensajes: 453
  • Programador
    • Ver Perfil
    • http://back2theretro.blogspot.com
Re: Interruciones
« Respuesta #6 en: Marzo 11, 2011, 17:10:58 »
Cita de: "Dr.Fred"

Os pongo un ejemplo de una interrupción que lee el teclado y escribe en pantalla. Lo que no consigo entender es en qué parte se llama a la interrupción en el programa... o simplemente poniendo la dirección en los dos bytes, ejecutaría mi interrupción... pero sólo lo haría una vez, porque se queda en un bucle infinito en la etiqueta HERE...  No sé... hay algo que no termino de ver.

[code]
MAIN    SEI
      LDA #00
      STA USRVTR
      LDA #$C1
      STA USRVTR+1
      CLI


HERE   JMP HERE


      EQU $C100
IRQ      JSR SCNKEY
      LDX +$C6
      BEQ OUT
      DEX
      STX +$C6
      LDA $0277
      JSR CHROUT
OUT      LDA IRQCTL
      PLA
      TAY
      PLA
      TAX
      PLA
      RTI
[/quote]

Tras un vistazo rápido:

En la parte Main, lo unico que hace es indicarle al sistema que
el nuevo vector de interrupción apunte a $C100, que es donde estará
la rutina etiquetada IRQ, tras esto la rutina se ejecutara 50 veces por segundo (PAL). luego llega al bucle infinito, si IRQ fuera llamada de otra manera que no fuera por una interrupción solo se ejecutaria una vez.

Como ves un bucle infinito en realidad no bloquea el sistema... Hay otras tareas que estan sucediendo por dentro (que nosotros percibimos paralelamente al programa actual en ejecución), como por ejemplo las rutinas llamadas por las interrupciones.

Para que veas como se harmonizan las interrupciones con el basic y ver un poco más acerca de las interrupciones,
te pongo este otro ejemplo donde la primera posicion de la memoria de video se va incrementando (mostrando un caracter distinto a cada vez que la interrupcion es llamada). Fijate que al volver el control a la misma rutina que se llamaba antes de modificar el vector, incluso podemos escribir cosas mientras la rutina sigue ejecutándose :wink:

Aqui programo la interrupción del primer chip CIA (complex interface adapter): hay dos CIA en el c64. En cada uno de estos chips podemos programar un reloj ("timers" A y B) que aquí se usa para poner la frecuencia de llamado de la interrupción 60 veces por segundo.

[code]         
               sei
               lda #<irq
               sta $0314
               lda #>irq
               sta $0315

               // frecuencia de la int($411a = 60 ints x sec.).
              lda #$1a     
              ldy #$41     
              sta $dc04    
              sty $dc05    

               // permite timer A en el CIA1
              lda #$81    
              sta $dc0d    

          // pone timer A en modo continuo
              lda #$91    
              sta $dc0e    
               cli
               rts
//----------------------------------
irq:         inc $0400   
               
            lda $dc0d    //hacer una lectura de este registro implica que la int volverá a ser rellamada despues
               asl $d019
               jmp $ea31    // salta a rutinas del vector original   [/quote]

Si no quieres regresar al basic (con RTS), puedes sustituir el jmp $ea31 por:

[code]PLA
      TAY
      PLA
      TAX
      PLA
      RTI[/quote]

que es basicamente el fragmente estandard de finalizacion de una rutina de interrupcion en el 6502. Si te fijas en un desensamblado de la ROM del basic verias que la rutina situada en $ea31, al final usa esto mismo tambien.

si quieres tambien en lugar del RTS pones HERE JMP HERE, como tenias en tu ejemplo, para lo del bucle infinito, y veras que los caracteres siguen girando... :wink:

NOTA: si usas RTS para regresar al basic, es necesario finalizar nuestra rutina con JMP $EA31 (que hará que el basic se comporte con normalidad)

Carlos

  • Desarrolladores
  • Commodore Master
  • ******
  • Mensajes: 652
    • Ver Perfil
Interruciones
« Respuesta #7 en: Marzo 12, 2011, 19:42:21 »
Dr. Fred, lobogris te lo ha dejado planchado...  :wink:

Dr.Fred

  • Commodoremaníaco
  • ****
  • Mensajes: 144
    • Ver Perfil
Interruciones
« Respuesta #8 en: Marzo 19, 2011, 22:44:29 »
Cita de: "Carlos"
Dr. Fred, lobogris te lo ha dejado planchado...  :wink:

Ya te digo! jajaja. Muchas gracias a los dos. Ya lo veo bastante más claro y además ya hemos empezado con ellas en clase. Ahora a hacer programillas toca.

Lo dicho, gracias!