Autor Tema: Consulta declaración de variables como UDATA  (Leído 3588 veces)

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

Desconectado ale141414

  • PIC10
  • *
  • Mensajes: 6
Consulta declaración de variables como UDATA
« en: 11 de Mayo de 2016, 22:14:32 »
Hola a todos,

Estoy usando la aplicación maestro de Microchip para controlar un LCD. En la librería generada las variables se declaran como UDATA, y ésto me trae un error de linkeo.

Variables declaradas como UDATA:

    UDATA

_vXLCDreg1      res 1
_vXLCDreg2      res 1
_vXLCDreg3      res 1         
_vXLCDtemp1     res 1
_vXLCDtemp2     res 1   ;used in XLCDDelay
_vXLCDStatus    res 1
   

Error de linkeo:

MPLINK 4.42, Linker
Device Database Version 1.7
Copyright (c) 1998-2011 Microchip Technology Inc.
Error - section '.udata' can not fit the section. Section '.udata' length=0x00000006
Errors    : 1

Link step failed.


En cambio si declaro las mismas variables con equ, el programa se compila y ejecuta de forma correcta.

Variables declaradas con equ:

_vXLCDreg1  equ 0x20
_vXLCDreg2  equ 0x21 
_vXLCDreg3  equ 0x22 
_vXLCDtemp1  equ 0x23
_vXLCDtemp2  equ 0x24
_vXLCDStatus  equ 0x25



Por ahora mi solución es declarar las variables con equ, pero por lo que leí, UDATA puede ser de hasta 256 y en éste caso es sólo de 6.

Mi pregunta es entonces si a alguien le pasó lo mismo, si pudo solucionarlo o si sabe porque pasa ésto.

Desde ya muchas gracias
Alejandro

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Consulta declaración de variables como UDATA
« Respuesta #1 en: 11 de Mayo de 2016, 22:30:26 »
De que PIC estamos hablando ?

Es para ver el archivo del linker

--------------------------------------

Voy a explicar levemente cual es la diferencia.

Código: ASM
  1. _vXLCDreg1  equ 0x20
  2. _vXLCDreg2  equ 0x21

El comando EQU, como el CBLOCK lo que hacen es asignar valores constantes. Veamos un ejemplo, esto es valido:

Código: ASM
  1. HOLA  EQU  1
  2.  
  3. BSF HOLA, HOLA

Observa que no se comprueba que realmente HOLA sea una direccion o un registro, simplemente se hace una sustitucion quedando BSF 1, 1
O mejor dicho poniendo a 1 el bit 1 de la direccion de memoria 0x01.

Otro ejemplo en el que supongamos que tenes memoria RAM desde 0x000 a 0x1FF, vos podes hacer:

Código: ASM
  1. HOLA EQU 0x200
  2.  
  3. BSF HOLA, 1

Es decir no le va a importar que se exceda, te puede llegar a dar un warning como maximo.
Otro ejemplo que suele pasar en personas que recien comienzan:

Código: ASM
  1. ;Archivo1.asm
  2.  
  3. CBLOCK 0x20
  4. Var1
  5. Var2
  6. Var3
  7. ENDC
  8.  
  9. ;Archivo2.asm
  10.  
  11. CBLOCK 0x20
  12. Var4
  13. Var5
  14. Var6
  15. ENDC

Var1 y Var4 ambos tienen asignado una constante que es 0x20. Y no se presenta ningun error al usuario.
Usualmente estos casos son mas faciles de implementar y explicar, que hacer lo mismo con la directiva udata.
Una cosa que tenes que darte cuenta es que sos vos quien posiciona exactamente en el lugar que desea cada "registro", y vos tenes que llevar el control. Esto no es muy lindo cuando por ejemplo usas un codigo en un PIC16 que su RAM comienza en 0x0C y en otro comienza en 0x20.
Existe una forma de hacerlo en el que el usuario NO se involucra en el posicionamiento del mismo. Y es con udata y udata_(aca hay varios).

En este caso vos le indicas al LINKER que reserve espacio para esa variable.

Código: ASM
  1. udata
  2. Var1  res 1
  3. Double res 2

El compilador procede a compilar el archivo y luego se lo da al LINKER quien acomoda los registros como desea y ademas termina completando el codigo.
Al usar esto se solucionan muchos problemas que ocurrian antes:

Código: ASM
  1. BSF Var1, Var1

Deberia darte un error.

Intentar poner variables donde no existe memoria, volvamos al ejemplo de 0x000 a 0x1FFF

Código: ASM
  1. udata 0x200
  2. Var1  res 1
  3. Double res 2

Deberia darte otro error. Diciendo que es imposible ponerlo en el lugar.

-----------------------------------------------------------------------------------------------------

Si observas el manual del MPASM ( compilador ) y el linker. Vas a notar que hay varios UDATA.

udata  (caso DATABANK en los archivos dle linker )
udata_acs ( para PIC18 y su ACCESS BANK )
udata_ovr  ( Caso en que sea necesario definir 2 variables con las mismas direcciones)
udata_shr  ( Caso de los SHAREBANK en los archivos del linker )

Y es aca donde importa realmente el PIC que usas. Ya que las divisiones de memoria muchas veces no son iguales, por ejemplo hay PICs que TODO banco1 se puede acceder desde el banco2
Entonces eso esta en el archivo del linker como SHARE, por lo cual vas a usar udata_shr para ocupar ese espacio.

Un ejemplo seria el PIC16F84A

Citar
SHAREBANK  NAME=gpr0       START=0xC             END=0x4F           
SHAREBANK  NAME=gpr0       START=0x8C            END=0xCF           PROTECTED

Pero por ejemplo un PIC16F887, tiene una parte de memoria que se puede acceder desde todos los bancos ( direccion de memoria 0x70 a 0x7F ) y luego tenes partes de memoria que pertenecen a un solo banco y no se puede acceder desde otro.

Citar
DATABANK   NAME=gpr0       START=0x20              END=0x6F           
DATABANK   NAME=gpr1       START=0xA0              END=0xEF           
DATABANK   NAME=gpr2       START=0x110             END=0x16F         
DATABANK   NAME=gpr3       START=0x190             END=0x1EF         

SHAREBANK  NAME=gprnobnk   START=0x70            END=0x7F           
SHAREBANK  NAME=gprnobnk   START=0xF0            END=0xFF           PROTECTED
SHAREBANK  NAME=gprnobnk   START=0x170           END=0x17F          PROTECTED
SHAREBANK  NAME=gprnobnk   START=0x1F0           END=0x1FF          PROTECTED

En el cual si quisiera ponerlo en la parte de sharebank, deberia usar udata_shr, sino solo udata.

Otro ejemplo de udata_shr, es que si queres reservar mas de 16 lugares ( 0x70 a 0x7F ) tendrias un error, por que es imposible poner algo mas grande en solo 16 lugares.
« Última modificación: 11 de Mayo de 2016, 23:22:09 por KILLERJC »

Desconectado ale141414

  • PIC10
  • *
  • Mensajes: 6
Re:Consulta declaración de variables como UDATA
« Respuesta #2 en: 11 de Mayo de 2016, 22:38:38 »
Ah si, perdón, me olvidé completamente

16F873A

Compilador:

MPASM Assembler (mpasmwin.exe) v5.44
MPLINK Object Linker (mplink.exe) v4.42
MPLIB Librarian (mplib.exe) v4.42

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Consulta declaración de variables como UDATA
« Respuesta #3 en: 11 de Mayo de 2016, 23:04:59 »
Edite arriba la respuesta y voy a seguir ese hilo asi que te recomiendo que lo leas antes.

El PIC16F873A, el archivo de linker:

Citar
LIBPATH .

CODEPAGE   NAME=page0      START=0x0               END=0x7FF                   
CODEPAGE   NAME=page1      START=0x800             END=0xFFF                   
CODEPAGE   NAME=.idlocs    START=0x2000            END=0x2003         PROTECTED
CODEPAGE   NAME=devid      START=0x2006            END=0x2006         PROTECTED
CODEPAGE   NAME=.config    START=0x2007            END=0x2007         PROTECTED
CODEPAGE   NAME=eedata     START=0x2100            END=0x217F         PROTECTED

DATABANK   NAME=sfr0       START=0x0               END=0x1F           PROTECTED
DATABANK   NAME=sfr1       START=0x80              END=0x9F           PROTECTED
DATABANK   NAME=sfr2       START=0x100             END=0x10F          PROTECTED
DATABANK   NAME=sfr3       START=0x180             END=0x18F          PROTECTED


SHAREBANK  NAME=gpr0       START=0x20            END=0x7F           
SHAREBANK  NAME=gpr0       START=0x120           END=0x17F          PROTECTED
SHAREBANK  NAME=gpr1       START=0xA0            END=0xFF           
SHAREBANK  NAME=gpr1       START=0x1A0           END=0x1FF          PROTECTED

SECTION    NAME=PROG1      ROM=page0           // ROM code space - page0
SECTION    NAME=PROG2      ROM=page1           // ROM code space - page1
SECTION    NAME=IDLOCS     ROM=.idlocs         // ID locations
SECTION    NAME=DEEPROM    ROM=eedata          // Data EEPROM

Observa que el DATABANK esta como PROTECTED, y que si te fijas las direcciones de memoria son los SFR, es decir los registros de los modulos.
Ahora la memoria que podes usar del banco 0 ( 0x20 a 0x7F )  es posible accederlo desde el banco 2 ( 0x120 a 0x17F ), es decir que da lo mismo si estas en el banco 2 o banco 0, si editas 0x20 o 0x120 vas a editar el mismo registro.
Al igual que los bancos 1 ( 0xA0 a 0xFF ) y el banco 3 (0x1A0 a 0x1FF). Este es el concepto del SHAREBANK.

Nuevamente podes observar que los espacios del banco 2 y 3 no se pueden crear "variables" ahi ( el PROTECTED ).

Entonces vamos a resumir un poco.

En ese PIC no tenes un DATABANK donde crear variables, todos estan PROTECTED en el cual no puede crearse nada. No hay espacio y por eso te tira el error.
Lo que tenes que reservar es espacio en los SHAREBANK.

La historia demasiado corta: USA udata_shr en ves de udata solo.

Y mucho cuidado con mezclar codigos que usan EQU/CBLOCK con codigos que usan udata sea el estilo que sea. Por que con udata el linker sabe que existe una variable ahi. Mientras que con lo demas es simplemente una sustitucion . Un ejemplo simple:

Código: ASM
  1. Var2  EQU 0x20
  2.  
  3.   udata_shr
  4.   Var1  res 1
  5.  
  6.   code
  7.  
  8.   BSF Var1, 0

Si lo haces en el PIC16F873A, el linker va a empezar a llenar la memoria y va a comenzar desde 0x20 ( el comienzo del SHAREBANK) pero el no sabe que hay un EQU, por que un EQU no es para eso. Lo usamos por "simplicidad", En ersumen el BSF, pondria a 1 el bit 0 de Var1 ( que se ubica en 0x20 ), y por equivocacion uno cree que Var2 es otra cosa, pero en realidad de usarlo estariamos accediendo a la misma, y en ves de tener 2 registros, es simplmente 1 solo.

Perdon por excederme pero espero haber sido claro. Sino por ahi existe un hilo sobre PIC18 ( el titulo) que lo explico tambien con ejemplos practicos. Aunque involucra se habla bastante tambien de programacion en general.

Sino sos libre de preguntar cualquier duda que se te presente.

PD:
Citar
Por ahora mi solución es declarar las variables con equ, pero por lo que leí, UDATA puede ser de hasta 256 y en éste caso es sólo de 6.

Como sabras ahora lo de 256 no se aplica. En ese PIC UDATA es de 0 y UDATA_SHR es de 190 lugares

El 6 que tenes ( ese lenght ) es la cantidad de lugares que estas intentando reservar:

Código: ASM
  1. _vXLCDreg1      res 1
  2. _vXLCDreg2      res 1
  3. _vXLCDreg3      res 1        
  4. _vXLCDtemp1     res 1
  5. _vXLCDtemp2     res 1   ;used in XLCDDelay
  6. _vXLCDStatus    res 1

Son 6 veces res 1, o mejor dicho reservaste 6, si cambiaras uno de esos por un res 2, verias que el error pasa a tener un legnth de 0x00007
« Última modificación: 11 de Mayo de 2016, 23:35:27 por KILLERJC »

Desconectado ale141414

  • PIC10
  • *
  • Mensajes: 6
Re:Consulta declaración de variables como UDATA
« Respuesta #4 en: 11 de Mayo de 2016, 23:36:26 »
No te excediste en nada. Aunque algunas cosas ya las sabía, siempre viene bien un repaso y me explicaste cosas que desconocía.

Una consulta, cuando te referís a que el LINKER termina completando el código, éste complemento se refiere a que agrega instrucciones para pasar de un banco a otro cuando se acceden a las variables que no son SHARE?

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Consulta declaración de variables como UDATA
« Respuesta #5 en: 11 de Mayo de 2016, 23:44:55 »
Me refiero a que el compilador lo unico que hace es revisar que este correctamente la sintaxis del codigo, y deja una tabla de "simbolos" para el linker. Quien es luego el que va a ubicar todos los codigos y reemplazar esos simbolos.

Por ejemplo luego del compilador una salida ademas del codigo objeto es el listing:
Código: [Seleccionar]
LOC  OBJECT CODE     LINE SOURCE TEXT
  VALUE

                      00001         list
                      00002 ;************************************************   
                      00003 ;   Definicion de variables
                      00004 ;************************************************   
                      00005         
  0000                00006         global  Var1
  0000                00007         extern  _Suma, Var3
                      00008     
                      00009 Bank0:  udata_acs
000000                00010 Var1:   res     1
000001                00011 Var2:   res     1
                      00012         
                      00013 ;************************************************   
                      00014 ;   Vectores de reset e interrupcion
                      00015 ;************************************************   
                      00016     
                      00017 Rst:    code    0x00    ;Vector de Reset
000000 EF?? F???      00018         GOTO    Main
                      00019     
                      00020         org    0x08     ;Vector de Interrupcion Alta Prioridad
000008 0012           00021         RETURN
                      00022     
                      00023         org    0x18     ;Vector de Interrupcion Baja Prioridad
000018 0012           00024         RETURN
                      00025 
                      00026 ;************************************************   
                      00027 ;   Programa Principal
                      00028 ;************************************************   
00001A                00029 Main:
00001A EC?? F???      00030     CALL    _Suma
00001E 0000           00031     NOP
000020 0E78           00032     MOVLW   0x78
000022 12??           00033     IORWF   Var3
000024 0000           00034     NOP
000026 EF?? F???      00035     GOTO    $           ;Loop infinito
                      00036
                      00037 ;----------- Fin de programa ---------------------       
                      00038     END

Como podes observar el CALL _Suma, el IORWF, y el GOTO, a la izquierda sus OPCODE estan incompletos. Esto por que todavia no paso por el linker, quien es el que realmente le va a dar un lugar en memoria y va a terminar completando eso.
Al compilador realmente no le importan donde este Var3, Solo que sea correcta la sentencia. El linker luego termina completando ese OPCODE cuando decide donde poner Var3.

Ahora me referia que el LINKER termina completando el codigo.

Dejo el link al otro post ( para no repetir todo ), aunque el tema viene de un poco mas atras y tambien trata otras cosas como el extern y el global ( para cortar con los includes al final del archivo ):
http://www.todopic.com.ar/foros/index.php?topic=45254.msg376641#msg376641

éste complemento se refiere a que agrega instrucciones para pasar de un banco a otro cuando se acceden a las variables que no son SHARE?

Realmente nunca tuve la oportunidad de tener TANTOS registros como para eso. Ya que de necesitar un buffer uno puede crear una seccion aparte y que comience desde una direccion que uno quiere, es decir es bastante complicado llegar a 95+ registros independientes entre uno y otro. Si quisiera tener un buffer, normalmente lo queres es una posicion contigua de memoria por lo cual tal ves lo lleves al banco 1:

Código: ASM
  1. Buffer udata_shr 0xA0
  2.     Buffer_RX res 64

Pero es buena tu pregunta. Ya que al uno no dedicarse a establecer al direccion del registro, debe conocer donde esta ubicado el mismo. Tal ves usando BANKSEL antes de operar con ese registro que es ahi donde el linker termina agregando por si solo las instrucciones correspondientes para acomodar donde iria. Tambien desconozco al no haber probado nunca es si estas en el mismo banco y usas un BANKSEL si se genera codigo o no.
« Última modificación: 12 de Mayo de 2016, 00:00:19 por KILLERJC »

Desconectado ale141414

  • PIC10
  • *
  • Mensajes: 6
Re:Consulta declaración de variables como UDATA
« Respuesta #6 en: 12 de Mayo de 2016, 19:52:02 »
Haciendo unas pruebas: sí, habría que previamente utilizar BANKSEL para acceder al registro, al compilar, el código no se genera sólo. Y si estás en el mismo banco y generas BANKSEL a un registro de ese banco el código se genera igual.

Otra vez, gracias a la solución de mi problema


 

anything