....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?
...
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
}
*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 Confused Serian unos cuantos ciclos que me ahorro a la entrada y salida de las interrupciones.
*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.
y en vez de usar la instruccion SWAPF, no se podria usar la instruccion MOVELW? Tampoco afecta al registro Z.
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.
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!
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. ¿?
*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?
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.
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).
*El direccionamiento indirecto que funcion tiene? Si podemos leer el registro directamente, para que lo vamos a leer de manera indirecta?
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.
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 ¿?
CitarLa 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
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?
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?
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.
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
004 MOVWF 0x70 005 SWAPF STATUS, W 006 MOVWF 0x71 . . . [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".
Y jacrmr, no seas tan duro con el chico, eh?
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
#int_global isr() { // Will be located at location 4 for PIC16 chips. #asm bsf isr_flag retfie #endasm }
Seguramente te benficiará el nuevo cambio de arquitectura de Microchip en toda su línea Mid-Range PIC12 y PIC16 que saldrá empezando el 2009. En estos dispositivos (que serán compatibles con los actuales) el contexto de la interrupción se guardará por hardware y no con software como se ha estado haciendo.
Espero que levanten la restriccion de los samples para probar estos micros nuevos :mrgreen: