Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Varios fallos al crear procedimientos escritura de EEPROM interna #6

Closed
AguHDz opened this issue Jun 8, 2017 · 11 comments
Closed

Varios fallos al crear procedimientos escritura de EEPROM interna #6

AguHDz opened this issue Jun 8, 2017 · 11 comments

Comments

@AguHDz
Copy link

AguHDz commented Jun 8, 2017

En esta prueba realizado con la versión 0.6.8 he conseguido escribir la EEPROM interna del microcontrolador PIC16F84A. En el siguiente código podemos ver los procedimientos empleados, ambos son equivalentes, pero uno está escrito en código ensamblador y el otro en Pascal.

// Prueba de esctritura en la EEPROM interna del PIC16F84A

{$FREQUENCY 8 MHZ }
{$PROCESSOR PIC16F84A}
program EEPROMInterna;

uses
  PIC16F84A;  
 
var
	EECON1   :byte absolute $08;  // FALLA ENSAMBLADOR SI SE DEJA $88.
	EECON2   :byte absolute $09;  // FALLA ENSAMBLADOR SI SE DEJA $89.

  Contador :byte;

procedure WriteEEPROMASM(direccion , valor: byte);
begin
ASM
ESCRITURA:               	 ; Establecer EEADR y EEDATA
		MOVF	direccion,w      ; Direccion de esctritura
		MOVWF	EEADR		         ; Escribe la dirección en EEADR
		MOVF	valor,w          ; Dato a escribir en EEPROM
		MOVWF	EEDATA 		       ; Se escribe el dato en EEDATA 
		BSF	STATUS,STATUS_RP0  ; (RP0) Selecciona el banco 1
		BSF	EECON1,EECON1_WREN ; (WREN) Permiso de escritura activado
;Comienzo de la secuencia de escritura
		MOVLW	$55
		MOVWF	EECON2		       ; Se escribe el dato 55 h en EECON2
		MOVLW	$AA
		MOVWF	EECON2		       ; Se escribe AA h en EECON2
		BSF	EECON1,EECON1_WR	 ; (WR)Comienza la escritura
		BCF	EECON1,EECON1_WREN ; (WREN) Permiso de escritura desactivado
ESPERA:
		BTFSC	EECON1,EECON1_WR ; (WR) Espera a que termine la escritura
		GOTO	ESPERA
		BCF	STATUS,STATUS_RP0  ; (RP0) Selecciona el banco 0
END
end;

procedure WriteEEPROM(direccion , valor: byte);
//var
//  WREN    : bit absolute EECON1.EECON1_WREN; // FALLA. No reconoce constantes.
//  WR     : bit absolute EECON1.EECON1_WR;   // FALLA. No reconoce constantes.
begin
  EEADR  := direccion;
  EEDATA := valor;
  ASM
    BSF	STATUS,5
  END
  EECON1.2 := 1;        // EECON1,EECON1_WREN := 1 // FALLA. No reconoce constantes.
  EECON2   := $55;
  EECON2   := $AA;
  EECON1.1 := 1;      // EECON1.EECON1_WR :=1 // FALLA. No reconoce constantes.
  EECON1.2 := 0;
  repeat until (EECON1.1 = 0);
  ASM
    BCF	STATUS,5
  END
end;

begin
  repeat
  for contador:=$00 to $10 do  
    WriteEEPROMASM(contador,$00);
  end;

  for contador:=$00 to $10 do  
    WriteEEPROM(contador,$FF);
  end;
  until false;
end.

Aunque ambos procedimiento graban la EEPROM perfectamente, ha sido necesario hacer ciertas correcciones para que funcione que no deberían haber sido necesarias. Estas correcciones evitar fallos del compilador y permiten generar un código que funciona correctamente.

Los fallos detectados son:

  • Ha sido necesario redefinir las variables EECON1 y EECON2 en direcciones del banco 0. Si se dejan las originales del banco 1 el código escrito en ensamblador falla.
  • En el procedimiento escrito en Pascal al intentar asignar un valor a los registros EECON1 y EECON2 (definidas en su direcciones originales, dejando en forma de comentarios los cambios del encabezamiento que las coloca en el banco 0), no se hace el cambio automático al banco 1 del SFR como lo hace cuando asignamos otros registros como los TRISs.
  • En el código Pascal no se reconocen las constantes definidas para asignar bits de los registros. En ensamblador funciona perfectamente BSF EECON1,EECON1_WREN, pero en Pascal EECON1,EECON1_WREN := 1; da error y tampoco se permite la definición de variable como bit del tipo WREN : bit absolute EECON1.EECON1_WREN;
@AguHDz
Copy link
Author

AguHDz commented Jun 8, 2017

Por cierto, he actualizado la librería PIC16F84A.pas (https://pastebin.com/i3PMcNGs) con los nombres de bits de SFR que aparecen en el DataSheet de Microchip. Había alguna discrepancia, al igual que ocurre en distintos manuales en internet sobre PICs. Por eso, creo que lo mejor es tomar siempre los nombres facilitados por el fabricante.

@t-edson
Copy link
Owner

t-edson commented Jun 8, 2017

Hola Agustín. Con respecto al problema de tener que definir EECON1 y EECON2 en el banco 0, y el porqué el compilador no hace los cambios de banco, no veo el problema. Déjame revisarlo.

Con respecto al error al usar la notación: EECON1,EECON1_WREN := 1;
No es una falla, sino un tema de sintaxis o semántico. PicPas identifica a EECON1_WREN, como constantes, y no es permitido, usar:
<byte>.<constante>

, para identificar a un campo de un byte. Por definición, PicPas, soporta solo:
<byte>.<identificador de campo de byte>

Y los únicos identificadores válidos para el tipo byte son: bit0, bit1, ... bit7. Si clao, también se puede usar 0, 1, .. 7, pero esto se mantiene solo por compatibilidad. Legalmente no se podrían usar números.
La verdadera sintaxis para hacer eso, sería tener que definir algo como:

VAR
  STATUS: byte ABSOLUTE $03  RECORD C , DC, Z, PD, _TO : Bit; RP : 0..3; END;

Y es lo que te comenté, con respecto a la sintaxis legal, de PicPas, para acceder a campos de un SFR. No está implementado por ahora, pero espero tenerlo pronto disponible, o al menos un acercamiento.

@AguHDz
Copy link
Author

AguHDz commented Jun 9, 2017

Hola t-edson, el resultado de compilar este procedimiento:

procedure WriteEEPROM(direccion , valor: byte);
begin
  EEADR  := direccion;
  EEDATA := valor;
  EECON1.2 := 1;
  EECON2   := $55;
  EECON2   := $AA;
  EECON1.1 := 1;
  EECON1.2 := 0;
  repeat until (EECON1.1 = 0);
end;

Es este:

__WriteEEPROM:
    ;EEADR  := direccion;
    $0011 movf direccion,w 
    $0012 movwf EEADR 
    ;EEDATA := valor;
    $0013 movf valor,w 
    $0014 movwf EEDATA 
    ;EECON1.2 := 1;
    $0015 bsf EEDATA, 2 
    ;EECON2   := $55;
    $0016 movlw 0x55 
    $0017 bsf STATUS, 5 ;Bank set.
    $0018 movwf EEADR 
    ;EECON2   := $AA;
    $0019 movlw 0xAA 
    $001A movwf EEADR 
    ;EECON1.1 := 1;
    $001B bcf STATUS, 5 ;Bank set.
    $001C bsf EEDATA, 1 
    ;EECON1.2 := 0;
    $001D bcf EEDATA, 2 
    ;repeat until (EECON1.1 = 0);
    $001E btfsc EEDATA, 1 
    $001F goto 0x01E 
    ;end;
    $0020 return  

Ves que antes de la dirección $0015 debería de haber cambiado al banco 1 y sin embargo lo hace en la dirección $0017, y no se por qué vuelve a cambiar al banco 0 en la dirección $001B, lo cual es incorrecto ya que a partir de ahí existen tres instrucciones que que trabajan con registros del banco 1.

Como digo, las instrucciones que cambiar los registros TRIS, también en el banco 1 funcionan perfectamente, probado incluso compilando código para 16F877A con los puertos C, D y E.

@AguHDz
Copy link
Author

AguHDz commented Jun 9, 2017

Otra solución, mientras implantas el modo de definir bits en RECORD, puede ser esta:

procedure WriteEEPROM(direccion , valor: byte);
var
  bitSFR_WREN   : bit absolute EECON1.2; // No reconoce constantes.
  bitSFR_WR     : bit absolute EECON1.1; // No reconoce constantes.
begin
  EEADR  := direccion;
  EEDATA := valor;
  ASM
    BSF	STATUS,5
  END
  bitSFR_WREN := 1;    // EECON1,EECON1_WREN := 1 // FALLA. No reconoce constantes.
  EECON2      := $55;
  EECON2      := $AA;
  bitSFR_WR   := 1;   // EECON1.EECON1_WR :=1 // FALLA. No reconoce constantes.
  bitSFR_WREN := 0;
  repeat until (bitSFR_WR = 0);
  ASM
    BCF	STATUS,5
  END
end;

Pero sería mucho mejor que se siguiera un solo criterio para llamar a los bits de los registros SFR. Ahora mismo, en las partes de programa escritas en ASM se definen como constantes (reciente implantado, lo que es muy de agradecer), y en las partes de código escritas en Pascal se definen como variables, y por lo tanto, es necesario darles otros nombres. Se puede dejar así, y funciona sin ningún problema, pero dobla es trabajo de crear librerías de registros para los distintos microcontroladores. De todos modos, la ventaja que le veo ahora mismo a PicPas es que ofrece distintos recursos para que si alguien sabe programar y entiende el código ensamblador casi siempre puede encontrar soluciones, pero entiendo que estas soluciones particulares para problemas concretos en cada programa pueden ser una barrera para quien tenga intención de empezar a usarlo o quiera simplemente aprender a programar microcontroladores PIC en lenguaje Pascal. Pero bueno, supongo que paso a paso se irán solucionando estos problemas normales cuando se afronta una labor tan compleja como programarse uno mismo su propio compilador. :)

@t-edson
Copy link
Owner

t-edson commented Jun 9, 2017

Efectivamente he comprobado que hay un "bug", en el manejo de bancos en PicPas. Hay una ligera corrección, que he hecho en esta misma versión 0.6.8 (tienes que actualziar de nuevo) y puede ayudar, pero el problema de fondo persiste y es un fallo en la asignación de bancos cuando se manejan procedimientos. Este tema es algo que estaré viendo en la siguiente versión, junto a otros pendientes. Mientras tanto te recomiendo que tengas cuidado cuando un procedimiento accede a variables de otros bancos. Puedes ayudarte de la función de sistema SetBank(), para fijar el banco de trabajo.

@t-edson
Copy link
Owner

t-edson commented Jun 9, 2017

Con respecto al problema que mencionas:

" Ha sido necesario redefinir las variables EECON1 y EECON2 en direcciones del banco 0. Si se dejan las originales del banco 1 el código escrito en ensamblador falla."

Quisiera que indiques, en qué sentido falla. ¿No compila? ¿No hace lo que debe hacer?
En mis pruebas, no detecto el error.

@AguHDz
Copy link
Author

AguHDz commented Jun 12, 2017

Hola t-edson.

Si compilo el siguiente código:

{$FREQUENCY 8 MHZ }
{$PROCESSOR PIC16F84A}
program EEPROMInterna;

uses
  PIC16F84A;  
 
var
  Contador :byte;

procedure WriteEEPROMASM(direccion , valor: byte);
begin
ASM
ESCRITURA:               	 ; Establecer EEADR y EEDATA
  MOVF	direccion,w      ; Direccion de esctritura
  MOVWF	EEADR		         ; Escribe la dirección en EEADR
  MOVF	valor,w          ; Dato a escribir en EEPROM
  MOVWF	EEDATA 		       ; Se escribe el dato en EEDATA 
  BSF	STATUS,STATUS_RP0  ; (RP0) Selecciona el banco 1
  BSF	EECON1,EECON1_WREN ; (WREN) Permiso de escritura activado
;Comienzo de la secuencia de escritura
  MOVLW	$55
  MOVWF	EECON2		       ; Se escribe el dato 55 h en EECON2
  MOVLW	$AA
  MOVWF	EECON2		       ; Se escribe AA h en EECON2
  BSF	EECON1,EECON1_WR	 ; (WR)Comienza la escritura
  BCF	EECON1,EECON1_WREN ; (WREN) Permiso de escritura desactivado
ESPERA:
  BTFSC	EECON1,EECON1_WR ; (WR) Espera a que termine la escritura
  GOTO	ESPERA
  BCF	STATUS,STATUS_RP0  ; (RP0) Selecciona el banco 0
END
end;

begin
  repeat
  for contador:=$00 to $10 do  
    WriteEEPROMASM(contador,$00);
  end;

  for contador:=$00 to $10 do  
    WriteEEPROMASM(contador,$FF);
  end;
  until false;
end.

En el emulador Proteus no funciona la escritura en la memoria interna EEPROM.
https://es.pinterest.com/pin/585468020279303851/

Pero si añado las dos siguientes línea para redefinir la posición de las variables EECON1 y EECON2.

var
  EECON1   :byte absolute $08;  // FALLA ENSAMBLADOR SI SE DEJA $88.
  EECON2   :byte absolute $09;  // FALLA ENSAMBLADOR SI SE DEJA $89.

  Contador :byte;

procedure WriteEEPROMASM(direccion , valor: byte);
begin ...

En la simulación de Proteus funciona y escribe la memoria EEPROM interna del uC sin problemas.
https://es.pinterest.com/pin/585468020279303851/

Existen compiladores en los que esto es normal, por lo que las librerías de SFR se definen todas en el banco 0, pero me parece que no es sería muy complicado poder utilizar las posiciones reales y que el compilador elimine los bits altos a partir de la dirección límite del banco 0. Por supuesto, en ensamblador el cambio de bancos es siempre labor del código ASM.

@t-edson
Copy link
Owner

t-edson commented Jun 14, 2017

Hola Agustín. Los fallos que mencionas deben estar ya corregidos en la nueva versión de PicPas, la 0.6.9, excepto el problema de acceso a los bits de un registro, usando constates, que como ya te indiqué, es un tema de sintaxis y no una falla.
Ten cuidado con los bancos de RAM cuando uses ASM. El compilador no sabe cuando se realizan cambios de banco, dentro de los bloques ASM.

@AguHDz
Copy link
Author

AguHDz commented Jun 14, 2017

Perfecto! Ahora funciona sin ningún problema.

Para el temas de las constantes, he actualizado la UNIT de los nombres de registro 16F84A.pas ( disponible en https://pastebin.com/4eRdCPzA ). Con ella, se evitan los problemas comentados, y por la forma de escribir el código en lenguaje Pascal y en Ensamblador, me parece incluso más coherente este uso de nombres de registros especiales y sus bits.

Ahora compila y funciona a la perfección el código escrito de esta manera (usando la UNIT 16F84A.pas actualizada):

{
*  (C) AguHDz 05-JUN-2017
*  Ultima Actualizacion: 14-JUN-2017
*
*  Compilador PicPas v.0.6.9 (https://github.com/t-edson/PicPas)
*
*  ESCRITURA DE DATOS EN EEPROM INTERNA DEL MICROCONTROLADOR
*  Ejemplo de uso de nombrea de variables y constantes definindas en nueva
*  UNIT 16F84A.pas, ahora mas coherente en el uso de los nombre de bytes y 
*  bits de la zona SFR de memoria y sus registros.
}

{$FREQUENCY 8 MHZ }
{$PROCESSOR PIC16F84A}
program EEPROMInterna;

uses
  PIC16F84A;  
 
var
  Contador :byte;

procedure WriteEEPROMASM(direccion , valor: byte);
begin
ASM
ESCRITURA:               ; Establecer EEADR y EEDATA
  MOVF	direccion,w      ; Direccion de esctritura
  MOVWF	EEADR		         ; Escribe la dirección en EEADR
  MOVF	valor,w          ; Dato a escribir en EEPROM
  MOVWF	EEDATA 		       ; Se escribe el dato en EEDATA 
  BSF	STATUS,bit_RP0     ; Selecciona el banco 1
  BSF	EECON1,bit_WREN    ; Permiso de escritura activado
;Comienzo de la secuencia de escritura
  MOVLW	$55
  MOVWF	EECON2		       ; Se escribe el dato 55 h en EECON2
  MOVLW	$AA
  MOVWF	EECON2		       ; Se escribe AA h en EECON2
  BSF	EECON1,bit_WR	     ; Comienza la escritura
  BCF	EECON1,bit_WREN    ; Permiso de escritura desactivado
ESPERA:
  BTFSC	EECON1,bit_WR    ; Espera a que termine la escritura
  GOTO	ESPERA
  BCF	STATUS,bit_RP0     ; Selecciona el banco 0
END
end;

procedure WriteEEPROM(direccion , valor: byte);
begin
  EEADR       := direccion;
  EEDATA      := valor;
  EECON1_WREN := 1;
  EECON2      := $55;
  EECON2      := $AA;
  EECON1_WR   := 1;
  EECON1_WREN := 0;
  repeat until (EECON1_WR = 0);
end;

begin
  repeat
  for contador:=$00 to $10 do  
    WriteEEPROMASM(contador,$00);
  end;

  for contador:=$00 to $10 do  
    WriteEEPROM(contador,$FF);
  end;
  until false;
end.

(Código disponible en https://pastebin.com/RzfpdyXU)

A ver que te parece la UNIT actualizada con definiciones de bytes y bits del SFR válidos para su uso tanto en Pascal como en ASM y lo pudieras actualizar ya en la versión actual de PicPas.

En cuanto a lo que comentas de selección de bancos en ASM, por supuesto, debe ser así. El programador debe decidir en que banco trabaja, y el compilador debe eliminar los bits altos de los registros SFR que están fuera del banco 0.

Por las pruebas realizadas hasta ahora, todos los problemas comentado quedan solucionados o aclarados perfectamente, y Picpas sigue mejorando en cada actualización. Gracias.

@t-edson
Copy link
Owner

t-edson commented Jun 14, 2017

Me parece muy bien la forma como has actualizado las unidades, hasta mientras no se tenga una mejor sintaxis.
Voy a actualizar las nuevas unidades, y a incluir tu ejemplo en la carpeta "/samples".
Una aclaración, si ya tienes definidas las variables bit, como STATUS_Z, puedes usar esa misma variable para acceder directamente desde el ensamblador:

uses PIC16F84A;
begin
  asm
	  BCF STATUS_Z
          BTFSC STATUS_Z
  end
end.

El ensamblador soporta ya desde la versión 0.6.7 referencias a variables bit y boolean. No sé si sea necesario definir adicionalmente la constante "bit_Z".

@AguHDz
Copy link
Author

AguHDz commented Jun 14, 2017

En ese caso, mejor. Son temas que si en una ocasión no funcionan y encuentras un modo de solucionarlas ya sigues metódicamente haciéndolas de la forma en que te funcionó. Acabo de probarlo con el siguiente procedimiento dejando en forma de comentarios las lineas de código actualizada. Supongo que me dio problemas en alguna versión previa a la 0.6.7, pero ahora reconoce perfectamente las variables tipo bit en el código ASM.

procedure WriteEEPROMASM(direccion , valor: byte);
begin
ASM
ESCRITURA:               ; Establecer EEADR y EEDATA
  MOVF	direccion,w      ; Direccion de esctritura
  MOVWF	EEADR		         ; Escribe la dirección en EEADR
  MOVF	valor,w          ; Dato a escribir en EEPROM
  MOVWF	EEDATA 		       ; Se escribe el dato en EEDATA 
;  BSF	STATUS,bit_RP0     ; Selecciona el banco 1
;  BSF	EECON1,bit_WREN    ; Permiso de escritura activado
  BSF	STATUS_RP0     ; Selecciona el banco 1
  BSF	EECON1_WREN    ; Permiso de escritura activado
;Comienzo de la secuencia de escritura
  MOVLW	$55
  MOVWF	EECON2		       ; Se escribe el dato 55 h en EECON2
  MOVLW	$AA
  MOVWF	EECON2		       ; Se escribe AA h en EECON2
;  BSF	EECON1,bit_WR	     ; Comienza la escritura
  BSF	EECON1_WR	     ; Comienza la escritura
;  BCF	EECON1,bit_WREN    ; Permiso de escritura desactivado
  BCF	EECON1_WREN    ; Permiso de escritura desactivado
ESPERA:
  BTFSC	EECON1,bit_WR    ; Espera a que termine la escritura
  GOTO	ESPERA
;  BCF	STATUS,bit_RP0     ; Selecciona el banco 0
  BCF	STATUS_RP0     ; Selecciona el banco 0
END
end;

Estoy de acuerdo en que se pueden eliminar las constantes tipo bit_XXX y llamar a los bits del SFR del mismo modo en el código Pascal y ASM.

@t-edson t-edson closed this as completed Jun 14, 2017
t-edson pushed a commit that referenced this issue Jul 10, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants