TODOPIC

Microcontroladores PIC => Almacén del Assembler => Mensaje iniciado por: KILLERJC en 06 de Octubre de 2015, 02:59:23

Título: PIC18 y sus misterios
Publicado por: KILLERJC en 06 de Octubre de 2015, 02:59:23
A pedido de RALF. Esto es un compilado de las cosas que pidieron que se explique de esa forma queda constancia y explicado en un solo lugar. Reservo este espacio para hacer un indice si es que se vuelve mas grande.

No intrduje codigos de ejemplos y simulaciones por que no crei necesario, si alguno desea que lo haga, agregare algunos. Tambien si desean alguna otra informacion la escribire.
Título: Re: PIC18 y sus misterios
Publicado por: KILLERJC en 06 de Octubre de 2015, 03:02:17
Direccionamiento de datos

Bueno como hay mucha gente con dudas con respecto a esto pense en escribir un hilo y dejar constancia para todos los demas.

El PIC18 es el primer PIC en introducir una memoria de datos lineal, basta de tener que estar cambiando bancos para cambiar algun registro de nuestros perifericos. Es un gran alivio, bueno.... En parte. Esto trajo problemas que vamos a ver mas adelante. La memoria RAM sigue estando dividida en "bancos" pero esta ves tenemos todos nuestros SFR ( Registros de nuestros perifericos ) al final en el ultimo banco.

Ademas otro cambio, es que posee un set mas rico de instrucciones, y como si fueran pocos cambios se puede habilitar mediante los bits de configuracion un set extendido de instrucciones.
¿Por que nos importa eso? por que el comportamiento de las instrucciones y del direccionamiento es distinto si esta activo o no el set extendido.


Para analizarlo las instrucciones poseen 4 tipos de direccionamiento:

- No tienen ( CLRWDT, SLEEP )
- Literal  ( En el que el dato va en el opcode y no en la memoria, ADDLW, MOVLW )
- Directo  ( En el que la direccion va en el opcode 8bits maximo, mas de la mitad de las instrucciones )
- Indirecto ( En el que se usa la direccion de los registros FSR )


El acceso indirecto permite el acceso a toda la memoria RAM sin preocuparnos por los bancos ya que el registro puede almacenar la direccion completa (12 bits) y no solo 8 bits como las instrucciones con acceso directo, solo debemos cargar la direccion al FSR y accedimos sin problemas.

Funcionamiento con set de instrucciones estandar (legacy , compatibilidad con los PIC16)

El acceso directo se separa en 2 partes:

- Por el Access Bank
- A traves del BSR

Cuando vemos las instrucciones observamos algo distinto a los PIC16

Código: ASM
  1. MOVF    f,d,a
  2.         DECF    f,d,a

¿Que es esa 'a' que aparece?, Si recordamos en los PIC16 solo teniamos f,d
Es decir f = direccion de registro ( 8 bits ) y d indicando a donde se escribe ( 1 = F, y 0 = W )
Pero ahora tenemos una 'a' que nos complica la vida.

Esa 'a' indica si va a acceder al Access bank o si va usar el registro BSR (Bank Select Register).
En el Access bank encontramos todos nuestros registros SFR, es decir los de nuestros perifericos. Y las primeras direcciones de memoria de la RAM de 0x00 a 0x5F
Mientras que con BSR (4 bits) podemos junto con los 8 bits del opcode generar todas las direcciones de la RAM.

¿Por que Microchip quiso complicarse la vida con esto? Es simple.
Supongamos que estamos en la direccion RAM 0x1.00 (separo en bytes asi se nota el banco y el opcode), si tenemos todos nuestros datos alli, y quisieramos poner a 1 o 0 el pin RB0, para eso deberiamos cambiar BSR por 0x1 para leer el dato, trabajo, cambio BSR a 0xF para poder cambiar el PORTB, luego tendria que cambiar nuevamente al anterior banco. Esto es ineficiente.

Entonces el señor Microchip levanto las tablas de instrucciones, dividio las aguas del rio y (http://www.ahiva.info/Gifs-Animados/Religion/Moises/Religion-397.gif) dijo:

Para evitar esto directamente usamos esa 'a' para indicar a que se refieren esos 8 bits.
Si 'a' es 0, la direccion a la que apunta esos 8 bits va a ser el banco 15 ( 0xF60 a 0xFFF ) y el caso que los 8bits sean menores a 0x5F apuntan al banco 0 ( 0x000 0x05F ) -Conocido como Access Bank
Si 'a' es 1, la direccion se va a formar con el BSR:opcode(8bits datos)

De esta forma mientras trabajamos en el banco 3 por ejemplo es posible acceder a los SFR eficientemente. Y no tenemos que estar cambiando el BSR a cada rato. Incluso podriamos acceder hasta 3 secciones de memoria a la misma ves, las primeras posiciones de memoria 0x00 a 0x5F, los SFR, y ademas todo el banco que estemos trabajando.

Esto en ASM ya viene definido, asi como tenemos W y F, el .inc agrega ACCESS y BANKED para la 'a', normalmente para mantener la compatibilidad con los PIC16 se puede omitir la 'a' asi el codigo es funcional tanto en uno como en otro, se asume que es ACCESS si no se incluye nada. Obviamente requiere algunas cosas mas como usar BANKSEL para el cambio de bancos, asi el compilador es el encargado de poner el codigo ese.


Funcionamiento con set de instruciones extendido ( aca se pierde toda la compatibilidad )

Este set presenta una mejora para programas en C el cual hace mucho uso de un stack. Hasta ahora no encuentro quien usa este set, desconozco tambien si XC8 aprovecha el set este o no. PERO por las dudas vamos a agregarlo aca para que nadie se sorprenda

Activar este set agrega unas 8 instrucciones mas, pero esto no es lo problematico, sino lo que es problematico es que tambien afecta al modo de direccionamiento de aquellas instrucciones que poseian un direccionamiento directo, que como se nombro es mas de la mitad de las instrucciones.

¿Como funciona cuando se activa este set?

Se podria separa nuevamente en dos. Cuando 'a' es 1, y cuando es 0.

- 'a' = 1 = BANKED
 Igual que en el caso anterior con el set estandar de instrucciones la direccion esta formada por el BSR:opcode(dato) , es decir ese modo no cambio para nada

- 'a' = 0 = ACCESS
 Este es el modo que cambia y bastante. Las dos situaciona se dan:
 - Cuando el opcode ( me refiero a los  8 bits de datos que lleva ) es mayor o igual a 0x60 accedemos como antes, es decir vamos a acceder al banco 15 donde estan nuestros SFR, igual que sin el set extendido.

 - Cuando el opcode es menor a 0x60 ( menor igual que 0x5F ) es cuando realemente cambia, esto hace que se pierda por asi decirlo el acceso directo y se cree un acceso indirecto con offset. Esta ves la direccion a la cual se va a acceder va a estar dada por el registro indirecto FSR2 (12 bits) + un offset de 8 bits dado por el opcode. Ejemplo si FSR2 = 0x210 y tenemos un

ADDWF [0x10],F,ACCESS

va a sumar lo que esta en la direccion 0x220 ( 0x210 + 0x10 ) con W y va a guardarlo en el mismo lugar (por la F).

Observaran que ahora la instruccion tiene unos corchetes  , esto es obligatorio en este set. Por esta forma de direccionamiento (que cambia como funcionan las instrucciones) y por como es la sintaxis de las instrucciones es que pierde la retro-compatibilidad
Título: Re: PIC18 y sus misterios
Publicado por: Miquel_S en 06 de Octubre de 2015, 04:49:12
Gracias KILLERJC me viene como anillo al dedo ya que estoy intentando aprender a usarlo, y la verdad que me encuentro con cosas que no termino de entender.

Saludos!
Título: Re: PIC18 y sus misterios
Publicado por: KILLERJC en 06 de Octubre de 2015, 05:21:07
En este post pidan y escribo sobre lo que pidan. Si da para ejemplos lo hago.
Título: Re: PIC18 y sus misterios
Publicado por: tapi8 en 06 de Octubre de 2015, 05:47:29
 ((:-)) ((:-)) ((:-))

Gracias nuevamente KILLERJC me hubieras venido muy bien hace unos meses cuando tuve que hacer mi primer y unico programa con PIC 18F, sin tener ni idea.

Creo que seria bueno ponerles chincheta a este post y al de los DSP ¿No os parece?.
Título: Re: PIC18 y sus misterios
Publicado por: KILLERJC en 06 de Octubre de 2015, 06:00:59
A este le falta todavia, al de DSP puede que si.
Título: Re: PIC18 y sus misterios
Publicado por: RALF2 en 06 de Octubre de 2015, 08:46:25
OOOOh muchas gracias KILLERJC,  su pequeño salta montes esta muy complacido, por ese gesto!  :mrgreen:

Seguire el hilo y hare las preguntas a que halla lugar  ;-)

Saludos
Título: Re: PIC18 y sus misterios
Publicado por: RALF2 en 06 de Octubre de 2015, 09:34:03
Seria bueno un ejemplito con los modos de direccionamiento (Access, Banked) me quedaron unas dudas  :?

Saludos
Título: Re: PIC18 y sus misterios
Publicado por: juaperser1 en 06 de Octubre de 2015, 09:48:50
KILLERJC no seas flojo y haz un tutorial de ASM, tanto de PIC como de ARM, el público te lo pide :D :D (yo en particular el de ARM xd)
Título: Re: PIC18 y sus misterios
Publicado por: yair_xiox en 06 de Octubre de 2015, 10:54:47
y un tutorial de las comunicaciones, spi,i2c,uart con los pic18 en asm seria bueno
Título: Re: PIC18 y sus misterios
Publicado por: KILLERJC en 06 de Octubre de 2015, 17:24:57
Seria bueno un ejemplito con los modos de direccionamiento (Access, Banked) me quedaron unas dudas  :?

Bueno voy a agregar codigos que se puedan simular para los modos de direccionamiento y algunos ejemplos incluso con los bits de los OPCODE, de esa forma pienso que ya no se va a escapar nada.

KILLERJC no seas flojo y haz un tutorial de ASM, tanto de PIC como de ARM, el público te lo pide :D :D (yo en particular el de ARM xd)

¿Sobre que exactamente lo de PIC? Ya hay un hilo explicando ASM:
http://www.todopic.com.ar/foros/index.php?topic=23623.0

Lo unico que puedo llegar a hacer es crear o agregarle una parte a eso, tales como algunas directivas para el posicionamiento de las variables,etc.
Sobre ARM tendras que esperar xD, todavia no termino con dsPIC, aunque ya tengo escrito una buena parte para agregar a lo dsPIC y finalizar con eso.
Para no complicarla demasiado voy a hacer un codigo mas que es la raiz cuadrada  de un numero con el dsPIC y fuerza bruta y de alli me mudo :P

y un tutorial de las comunicaciones, spi,i2c,uart con los pic18 en asm seria bueno

Esta no la inclui por que generalmente son iguales para todos los modulos, al poder simularlo de un solo lado, lo unico que puedo hacer es mostrar una plantilla de como seria el codigo. Pero que seria demasiado simple:

Configuracion

Usarlo

El tema de la configuracion esta paso a paso en el datasheet Y es normalmente 2 o 3 registros. Ahi dice si queres habilitarlo en modo X, hace los siguientes pasos. Y te indica bit a bit que hay que cambiar...
Tambien cada modulo tiene varias opciones, que todas estan explicadas por internet, siento que es como repetir todo. Pero bueno ya voy a pensarlo un poco.
Título: Re: PIC18 y sus misterios
Publicado por: juaperser1 en 06 de Octubre de 2015, 17:30:38
Citar
¿Sobre que exactamente lo de PIC? Ya hay un hilo explicando ASM:
http://www.todopic.com.ar/foros/index.php?topic=23623.0

Lo unico que puedo llegar a hacer es crear o agregarle una parte a eso, tales como algunas directivas para el posicionamiento de las variables,etc.
Sobre ARM tendras que esperar xD, todavia no termino con dsPIC, aunque ya tengo escrito una buena parte para agregar a lo dsPIC y finalizar con eso.
Para no complicarla demasiado voy a hacer un codigo mas que es la raiz cuadrada  de un numero con el dsPIC y fuerza bruta y de alli me mudo Razz

A mi lo de Pic me da igual, lo he puesto por solidarizarme con los demás, pero me importa un pimiento  :D :D YO QUIERO ARM, QUE NUNCA HE HECHO NADA DE ASM EN ARM :D :D Y CUANDO MIGRE SERÁ CON TODAS LAS DE LA LEY :D

así que bueno me esperaré  :mrgreen: :mrgreen:
Título: Re: PIC18 y sus misterios
Publicado por: RALF2 en 06 de Octubre de 2015, 17:37:48
juaperser1
Citar
A mi lo de Pic me da igual, lo he puesto por solidarizarme con los demás, pero me importa un pimiento  lol lol

Yo llevos años programando y trabajando con los pic, asi que te agradesco que no desvies del tema al maetro KILLEJC, sino te voy a colgar de la orejas  :D :D :D
Asi que haz tu cola (fila)  :D :D

Saludos
Título: Re: PIC18 y sus misterios
Publicado por: juaperser1 en 06 de Octubre de 2015, 17:48:40
Citar
Yo llevos años programando y trabajando con los pic

yo también, mas concretamente con los PIC32 y por eso quiero huir ya  :D

Citar
Yo llevos años programando y trabajando con los pic, asi que te agradesco que no desvies del tema al maetro KILLEJC, sino te voy a colgar de la orejas  lol lol lol
Asi que haz tu cola (fila)  lol lol

(para mis adentros) malditos moderadores siempre mandando...

 :D :D :D :D

PD: es broma a ver si ahora me vais a banear  :D :D
Título: Re: PIC18 y sus misterios
Publicado por: yair_xiox en 06 de Octubre de 2015, 18:39:32
también me interesa lo de asm en arm para aprender a programar los arm
Título: Re: PIC18 y sus misterios
Publicado por: KILLERJC en 07 de Octubre de 2015, 05:06:23
A pedido de RALF vamos a dar un par de ejemplos. Voy a usar un PIC18F2550, ya que es comun.

Primero que nada vamos a ver el archivo del linker asi vemos como esta separada su memoria. El archivo en cuestion se llama 18f2550_g.lkr, en este tenemos podemos ver 2 secciones y el conflicto al momento de activar el set de instrucciones extendido.


Primero tenemos la Flash, ahi vemos nuestra memoria "page", tenemos los fuses en config, tenemos el ID del PIC en "idlocs" y tenemos la memoria EEPROM como "eedata"

Código: [Seleccionar]
CODEPAGE   NAME=page       START=0x0               END=0x7FFF
CODEPAGE   NAME=idlocs     START=0x200000          END=0x200007       PROTECTED
CODEPAGE   NAME=config     START=0x300000          END=0x30000D       PROTECTED
CODEPAGE   NAME=devid      START=0x3FFFFE          END=0x3FFFFF       PROTECTED
CODEPAGE   NAME=eedata     START=0xF00000          END=0xF000FF       PROTECTED

Luego continua la RAM y esta esta separada en 2 partes


Código: [Seleccionar]
#IFDEF _EXTENDEDMODE
  DATABANK   NAME=gpre       START=0x0               END=0x5F
#ELSE
  ACCESSBANK NAME=accessram  START=0x0               END=0x5F
#FI

La primera dependiendo si esta activo o no el set va a funcionar de una u otra forma, como dijimos si tenemos un ACCESS = 'a'= 0 y una direccion menor a 0x60, va a funcionar de distinta forma. Y en el caso que no este activado el set extendido ese pedazo de memoria se clasifica como ACCESSBANK
Seguido de esto solamente quedan los demas bancos ( ver el DATABANK ) y los SFR (otra ves ACCESBANK):

Código: [Seleccionar]
DATABANK   NAME=gpr0       START=0x60              END=0xFF
DATABANK   NAME=gpr1       START=0x100             END=0x1FF
DATABANK   NAME=gpr2       START=0x200             END=0x2FF
DATABANK   NAME=gpr3       START=0x300             END=0x3FF
DATABANK   NAME=gpr4       START=0x400             END=0x4FF
DATABANK   NAME=gpr5       START=0x500             END=0x5FF
DATABANK   NAME=gpr6       START=0x600             END=0x6FF
DATABANK   NAME=gpr7       START=0x700             END=0x7FF
ACCESSBANK NAME=accesssfr  START=0xF60             END=0xFFF          PROTECTED


OK, visto el linker todavia no vimos ningun ejemplo xD. Lo lamento pero estoy mostrando lo que no normalmente no se ve. Y donde encontrar las respuestas. Asi la gente se familiariza con lo que es el linker, el compilador, etc.

Primero vamos a probar algun codigo con el set de instrucciones estandar, para poder comparar y como todas las instrucciones que tengan esa 'a' en su instruccion van a actuar igual. Lo que vamos a hacer es usar una unica instruccion, en este caso es

Código: ASM
  1. ADDWF f,d,a

Esta nos va a permir cargar un numero en W e intentar repartirlo a donde sea. Para eso creamos este codigo:


CODIGO COMPLETO PARA EL SET ESTANDAR
Código: ASM
  1. ;************************************************    
  2. ;   INCLUDES
  3. ;************************************************
  4.    
  5. #include "p18f2550.inc"
  6.  
  7.    
  8. ;************************************************    
  9. ;   Definicion de variables
  10. ;************************************************    
  11.  
  12.    ; Solo PIC18
  13.    ; Udata - Data no inicializada
  14.    ; Access data
  15.    ; Ubicacion: 0x00 a 0x5F
  16.     udata_acs
  17. Var1:   res     1
  18. Var2:   res     1
  19. Buff:   res     8
  20.    
  21.     ; Udata - Data no inicializada
  22.     ; Comienza en 0x60 el banco 0 ( DAATBANK ) si es que no coloco una direccion
  23.     ; Lo acomoda solo el linker, basta de renegar con CBLOCKS
  24. Bank0:  udata  0x89
  25. V1:     res     1
  26. V2:     res     1
  27. V3:     res     1
  28.  
  29.  
  30.     ; Udata
  31.     ; Variables puestas en el 5to banco
  32. Bank5:  udata  0x500
  33. BVar1:  res     1
  34. BVar2:  res     1
  35. BVar3:  res     1
  36.  
  37.        
  38. ;************************************************    
  39. ;   Vectores de reset e interrupcion
  40. ;************************************************    
  41.    
  42.    
  43.        
  44. Rst:    code    0x00    ;Vector de Reset
  45.         GOTO    Inicio
  46.    
  47. IntB:   code    0x08    ;Vector de Interrupcion Alta Prioridad
  48.         RETURN
  49.    
  50. IntA:   code    0x18    ;Vector de Interrupcion Baja Prioridad
  51.         RETURN
  52.  
  53.    
  54. ;************************************************    
  55. ;   Configuracion de modulos
  56. ;************************************************
  57.    
  58. Inicio:
  59.    
  60.     ; Ponemos el Puerto B como todas salidas
  61.     CLRF    LATB        ; Limpiamos los latch de salida
  62.     MOVLW   0x0E        ; Seteamos Rb4:0 como digitales
  63.     MOVWF   ADCON1      ; Solo por si alguno activo el FUSE PBADEN
  64.     CLRF    TRISB       ; Ponemos todo el puerto como salida
  65.    
  66. ;************************************************    
  67. ;   Programa Principal
  68. ;************************************************    
  69.    
  70. Main:
  71.     MOVLW   0x10                ; Cargo un valor y empiezo a sumar
  72.     MOVLB   0x0                 ; Me aseguro que comienze en el banco 0
  73.    
  74.     ADDWF   Var1, F, ACCESS     ;Var1 ubicado en 0x00
  75.     ADDWF   BVar1, F, ACCESS    ;Bvar1 ubicado en 0x500
  76.     ADDWF   V1, F, ACCESS       ;V1 ubicado en 0x66    
  77.    
  78.     NOP
  79.     GOTO    $                   ;Loop infinito
  80.  
  81. ;----------- Fin de programa ---------------------        
  82.     END


Tengo los bits de los fuses en otro archivo solo para que no moleste en el codigo. Bueno primero que nada vemos un par de diferencias. A lo que estamos acostumbrados y es el no usar CBLOCK !. CBLOCK simplemente asigna constantes y ahi comienzan los problemas. Supongamos esto que es TAN TAN comun:

Archivo1.asm:
Código: ASM
  1. CBLOCK
  2. Var1
  3. Var2
  4. Var3
  5. ENDC
  6.  
  7. ...
  8.  
  9. ;final del archivo
  10. #include(Archivo2.asm) ;delay te suena?

Archivo2.asm (Libreria):
Código: ASM
  1. CBLOCK
  2. LibVar1
  3. LibVar2
  4. LibVar3
  5. ENDC

Eso no es crear una variable. El linker no tiene ni la menor idea que es una variable eso. CBLOCK asigna constantes. Es como tener muchos EQU, pero permite achicarlo mas obviamente

Código: ASM
  1. Var1 EQU 0x00

Y comienza con el valor que se le da, si no se le da un valor comienza por 0x00, ¿se puede usar?, por supuesto!, para un programa con codigo absoluto es genial. pero hacer lo que puse antes va a llevar que LibVar1 se le asigne un 0, y en el primer archivo Var1 igual es 0.

Entonces si luego hacemos: ADDWF Var1,F o ADDWF LibVar1,F

Ambos son iguales que hacer: ADDWF 0x00,F

Para solucionar esta mala usada y problemas de programacion, como cuando cambian de PIC y se encuentran que la RAM comienza en 0x20 y no en 0x0C y terminan escribiendo los registros de los perifericos, solo quedaba de poner todo las variables en un CBLOCK solo, o de contar las variables, y que el otro archivo comienze con ese offset, si seguimos el ejemplo

Archivo1.asm:
Código: ASM
  1. CBLOCK 0x20
  2. Var1
  3. Var2
  4. Var3
  5. ENDC
  6.  
  7. ...
  8.  
  9. ;final del archivo
  10. #include(Archivo2.asm)

Archivo2.asm (Libreria):
Código: ASM
  1. CBLOCK  0x23
  2. LibVar1
  3. LibVar2
  4. LibVar3
  5. ENDC

Ahora imaginate con varios archivos , y agregar una sola "variable" al comienzo, ¿Hermoso trabajo no?
Otro es el de incluir archivos (si otra hermosura es eso de poner el include de los delay al ultimo),
La desicion es de cada uno. de usarlo o no, yo en el codigo hice un codigo que se le llama "Relocatable" el cual permite agregar mas variables sin problemas.

Al comienzo del post elegi mostrar el archivo del linker e hice especial atencion a lo de ACCESSBANK y DATABANK ( o al menos lo intente ).

Yo use las siguientes directivas:

Código: [Seleccionar]
Nombre seccion: udata_acs Direccion
Nombre seccion: udata Direccion

udata_acs usa el ACCESSBANK del linker, como ven los unicos lugares son de las memorias 0x00 a 0x5F
y udata, reserva en cualquier lugar que seas el DATABANK. Si no le das direccion el linker lo acomoda solo

¿Resumen? POR FAVOR

Le dije al linker que tengo 3 variables en el ACCESBANK, entonces el linker decidio de ponerlos en la direccion 0x00, luego a los demas le di direccion de memoria y asi quedaron:

Código: [Seleccionar]
Nombre Direccion

Var1 0x00
Var2 0x01
Buff 0x02-0x09
V1 0x89
V2 0x8A
V3 0x8B
BVar1 0x500
BVar2 0x501
BVar3 0x502


Esto puedo verlo en la memoria de datos cuando lo este simulando. Ahora vamos a ver que pasa con cada instruccion que agregamos, el OPCODE de la instruccion ADDWF f,d,a es

Código: [Seleccionar]
0010 01da ffff ffff
ahi se puede ver que bit es el de la d, el de la a, y que f solo ocupa 8bits que opcodes generarian estas instrucciones?

Código: ASM
  1. ADDWF   Var1, F, ACCESS         ;0010 0110 0000 0000
  2.     ADDWF   BVar1, F, ACCESS            ;0010 0110 0000 0000
  3.     ADDWF   V1, F, ACCESS               ;0010 0110 1000 1001

Primero notar que las 2 primeras instrucciones son iguales en opcde, a pesar que BVar1 esta en 0x500, pero solo toma 8 bits,

Al hacer esas instrucciones paso a paso queda asi:

Código: [Seleccionar]
Var1 = 0x10 - 1era instruccion
Var1 = 0x20 - 2da instruccion
LATA = 0x10 - 3era instruccion

Al ser de 8 bits el lugar para f en el opcode ,solo tomo nomas 0x00 y accedo al banco 0 con direcciones 0x00 a 0x5F ( access bank ). En el caso de la tercera instruccion al ser mayor o igual a 0x60 y seleccionar ACCESS accedio a los SFR, puse a proposito esa direccion para que coincidiera con LATA ( por si las dudas )

Nada que ver lo que quisimos hacer xD. Pero bueno esto demuestra lo errado de esas instrucciones. Como acceder correctamente a esos lugares? Asi que vamos a cambiar un poco las instrucciones. Asi que cambie el codigo por este:


Código: ASM
  1. Main:
  2.     MOVLW   0x10                ; Cargo un valor y empiezo a sumar
  3.  
  4.     MOVLB   0x5                 ; Banco 5
  5.     ADDWF   Var1, F, ACCESS     ; Var1 ubicado en 0x00
  6.     ADDWF   BVar1, F, BANKED    ; Bvar1 ubicado en 0x500
  7.     MOVLB   0x0
  8.     ADDWF   V1, F, BANKED       ;V1 ubicado en 0x89    
  9.    
  10.     GOTO    $                   ;Loop infinito

Al hacer eso tengo los siguientes resultados (paso a paso igual que antes):

Código: [Seleccionar]
Var1(0x000) = 0x10
BVar1(0x500) = 0x10
V1(0x089) = 0x10

Esto es lo que hace el acceso directo. Podriamos haber aprovechado que estabamos en el banco 0 al comienzo y cambiado el orden, asi tener el mismo resultado

Código: ASM
  1. Main:
  2.     MOVLW   0x10                ; Cargo un valor y empiezo a sumar
  3.     MOVLB   0x0                 ; Banco 5
  4.    
  5.     ADDWF   Var1, F, ACCESS     ; Var1 ubicado en 0x00
  6.     ADDWF   V1, F, BANKED       ;V1 ubicado en 0x89    
  7.     BANKSEL BVar1
  8.     ADDWF   BVar1, F, BANKED    ; Bvar1 ubicado en 0x500
  9.    
  10.     GOTO    $                   ;Loop infinito

Ahi se observa que como el banco estaba en cero con banked pude acceder a todo. Y se preguntaran. Que ocurriria si yo utilizo una instruccion con una direccion menor a 0x60 y le pongo el BANKED. Bueno para eso simplemente 2 lineas simples

Código: ASM
  1. ADDWF   Var1, F, ACCESS ; opcode 0x2600
  2.     ADDWF   Var1, F, BANKED     ; opcode 0x2700

Resultado

Código: [Seleccionar]
Var1(0x00) = 0x10
Var1(0x00) = 0x20

Si, el banked le importa nada la direccion. solo le hace caso al banco que esta seleccionado y listo. Y hace uso de sus 8 bits del opcode para la direccion formar la direccion.
Ahh una cosa.. Si observaron puse un BANKSEL , esto es bueno por que si yo coloco en cualquier otro lado mi variable, no debo cambiar el valor del banco ahi, directamente el linker le agregar una linea.
Para el caso del PIC18 es un MOVLB

Que nos queda? El direccionamiento Indirecto. Supongamos que teniamos el mismo caso que recien. En el que tenia una variable en el banco 5 ( 0x500 ) y tenemos que estar cambiando ese y el del banco 0 (0x89).
Primero que nada ver lo irrealista que esto, en el access bank deberias tener lo que siempre usas. ya que podes acceder a el en cualquier lugar sin necesidad de cambiar bancos, luego podrias tener todas tus variables en un banco.Y se evitaria el problema que comento arriba, pero es un ejemplo.

Código: ASM
  1. Main:
  2.     MOVLW   0x10                ; Cargo un valor y empiezo a sumar
  3.     MOVLB   0x0                 ; Banco 5
  4.     LFSR    2,BVar1
  5.    
  6.     ADDWF   Var1, F, ACCESS     ; Var1 ubicado en 0x00
  7.     ADDWF   V1, F, BANKED       ;V1 ubicado en 0x89    
  8.     ADDWF   INDF2, F, ACCESS    ; Bvar1 ubicado en 0x500
  9.     NOP
  10.    
  11.     GOTO    $                   ;Loop infinito

Al termino de la direccion LFSR, el par de registros FSR2 se carga con 0x500 y luego puedo acceder a lo que hay en esa direccion con INDF2, registro que se encuentra en los SFR, se hace notar que no cambio de banco para nada. Paso a paso nuevamente:

Código: [Seleccionar]
Var1 (0x000) = 0x10
V1 (0x089) = 0x10
BVar1 (0x500) = 0x10

El direccionamiento indirecto como ven no depende de elegir el banco, es capaz de direccionar toda la memoria con sus 12bits.

Por ultimo vamos a activar el set extendido y ver si realmente funciona asi o no...
Para eso tengo que activarlo desde la configuracion de proyectos. El primer cambio que encontramos es que ya no existe mas el ACCESSBANK, si recordamos el linker, este no existiria. Asi que si intentamos compilar el otro codigo nos vamos a encontrar con ese error. Es imposible meter una variable ahi.
Asi que este es el esqueleto del programa:

CODIGO COMPLETO PARA EL SET EXTENDIDO
Código: ASM
  1. ;************************************************    
  2. ;   INCLUDES
  3. ;************************************************
  4.    
  5. #include "p18f2550.inc"
  6.  
  7.    
  8. ;************************************************    
  9. ;   Definicion de variables
  10. ;************************************************    
  11.  
  12.     ; Udata - Data no inicializada
  13.     ; Comienza en 0x00 si es que no coloco una direccion, ya no hay mas ACCESSBANK, solo DATABANK
  14.     ; Lo acomoda solo el linker, basta de renegar con CBLOCKS
  15. Bank0:  udata  0x00
  16. Var1:   res     1
  17. Var2:   res     1
  18. Var3:   res     1
  19.        
  20. Bank01: udata  0x89
  21. V1:     res     1
  22. V2:     res     1
  23. V3:     res     1
  24.  
  25.     ; Udata
  26.     ; Variables puestas en el 5to banco
  27. Bank5:  udata  0x500
  28. BVar1:  res     1
  29. BVar2:  res     1
  30. BVar3:  res     1
  31.  
  32.        
  33. ;************************************************    
  34. ;   Vectores de reset e interrupcion
  35. ;************************************************    
  36.    
  37.    
  38.        
  39. Rst:    code    0x00    ;Vector de Reset
  40.         GOTO    Inicio
  41.    
  42. IntB:   code    0x08    ;Vector de Interrupcion Alta Prioridad
  43.         RETURN
  44.    
  45. IntA:   code    0x18    ;Vector de Interrupcion Baja Prioridad
  46.         RETURN
  47.  
  48.    
  49. ;************************************************    
  50. ;   Configuracion de modulos
  51. ;************************************************
  52.    
  53. Inicio:
  54.    
  55.     ; Ponemos el Puerto B como todas salidas
  56.     CLRF    LATB            ; Limpiamos los latch de salida
  57.     MOVLW   0x0E            ; Seteamos Rb4:0 como digitales
  58.     MOVWF   ADCON1, ACCESS  ; Solo por si alguno activo el FUSE PBADEN
  59.     CLRF    TRISB           ; Ponemos todo el puerto como salida
  60.    
  61. ;************************************************    
  62. ;   Programa Principal
  63. ;************************************************    
  64.    
  65. Main:
  66.     MOVLW   0x10                ; Cargo un valor y empiezo a sumar
  67.     MOVLB   0x0                 ; Banco 5
  68.     LFSR    2,0x300             ; Apuntando al banco 3
  69.  
  70.     NOP
  71.    
  72.     GOTO    $                   ;Loop infinito
  73.  
  74. ;----------- Fin de programa ---------------------        
  75.     END


No cambiamos casi nada solo cambie el udata_acs por udata de esa forma teniamos algo "equivalente" a nuestro ejemplo anterior. Vamos a probar lo mismo reemplazando ese NOP por lo siguiente:

Código: ASM
  1. ADDWF   Var1, F, ACCESS
  2.     ADDWF   BVar2, F, ACCESS
  3.     ADDWF   V1, F, ACCESS

Cambie la segunda linea por BVar2 (0x501). Resultado:

Código: [Seleccionar]
Memoria 0x300 = 0x10
Memoria 0x301 = 0x20
LATA = 0x10

Peor xD.
Como se puede ver yo a proposito puse el FSR2 en 0x300 al comienzo del programa. mi idea era justamente esa. Aqui podemos ver que en ACCESS y con el set extendido, tenemos que cuando la direccion es menor a 0x60 ( Reocordar que solo pueden ir 1 byte en el opcode y BVar solo dejaria 0x01 ) lo que se hace es acceder a la direccion del FSR2 + offset dado por el byte del opcode, en la primera es 0x300 + 0x00, en la segunda instruccion es 0x300 + 0x01 y por ultimo al hacer la 3ra instruccion alojado en 0x89, accedemos a los SFR como antes.

Esto es lo unico que cambia con respecto al otro. Y como que no utilizarias nunca el nombre de un registro para eso ya que lo que te interesaria seria poner el valor base con el FSR2 y luego acceder a cada valor con un offset, supongamos que quiero ponerles un 0x10 a los valores de memoria 0x120 ,0x125, 0x150.

Con el set extendido, yo puedo hacer eso con esto:
Código: ASM
  1. LFSR    2,0x120
  2.         ADDWF   [0x0],F
  3.         ADDWF   [0x5],F
  4.         ADDWF   [0x30],F

Título: Re: PIC18 y sus misterios
Publicado por: Miquel_S en 07 de Octubre de 2015, 09:22:14
Le dije al linker que tengo 4 variables en el ACCESBANK, entonces el linker decidio de ponerlos en la direccion 0x00, luego a los demas le di direccion de memoria y asi quedaron:

Código: [Seleccionar]
Nombre Direccion

Var1 0x00
Var2 0x01
Buff 0x03-0x08
V1 0x89
V2 0x8A
V3 0x8B
BVar1 0x500
BVar2 0x501
BVar3 0x502


Esto puedo verlo en la memoria de datos cuando lo este simulando. Ahora vamos a ver que pasa con cada instruccion que agregamos, el OPCODE de la instruccion ADDWF f,d,a es

Lo siento no encuentro lo de la memoria de datos para poder visualizar el ejemplo, solo encuentro Program Memory, o tengo que añadir estas lineas al Linker, de ser asi ¿Donde?

Nombre seccion:      udata_acs   Direccion
Nombre seccion:      udata      Direccion

Y GRACIAS por el tutorial que estas haciendo.
Título: Re: PIC18 y sus misterios
Publicado por: KILLERJC en 07 de Octubre de 2015, 09:39:11
No al linker no lo tocas, solo lo mostre como es y como esta definida la memoria.


Para ver la memoria de datos:

En el mismo lugar donde ves el Progra Memory abajo hay 2 listas
En la de la izquierda elegi  "File Registers"

Podes elegir luego el formato con las lista de la derecha
"Symbols" esta bueno para ver la memoria y vas a ver que el linker asigna el lugar y le pone el valor de la etiqueta, lo feo es que se necesita hacer un scroll muy largo para recorrer la memoria
"Hex" no te muestra nada de etiquetas, pero podes llegar mas rapido a ver todas las memorias, un simple scroll y estas por el 0x300

Como vos le dijiste al linker que son variables. Tranquilamente cuando lo simulas podes abrir en Window -> Debuging -> Variables
Ahi haces click a la izquierda que hay un diamante con un + y te permite elegir todas las variables, estan como "Global symbols", solo se cargan cuando lo simulas.

¿Tenes que agregar algo?

No, para nada. Tenes 2 archivos "completos", 1 con el set standard que es el primero y el otro con el set extendido, ahi lo voy a resaltar en el post

Lo unico que podes/tenes que cambiar es lo de dentro del Main, lo demas lo dejas como esta hasta probar todo.



A mi lo de Pic me da igual, lo he puesto por solidarizarme con los demás, pero me importa un pimiento  :D :D YO QUIERO ARM, QUE NUNCA HE HECHO NADA DE ASM EN ARM :D :D Y CUANDO MIGRE SERÁ CON TODAS LAS DE LA LEY :D

así que bueno me esperaré  :mrgreen: :mrgreen:

Hoy hice el archivo del linker, con las secciones .data , .text y .bss
Tengo que hacer el archivo startup.s con el codigo de inicializacion de datos en la RAM + stack ( tengo que hacer el codigo y tengo una parte de un ejemplo )
Tengo que hacer el archivo main.s con un loop infinito, el mas corto de todos
Me habia puesto a hacer el Makefile, le falta bastante. especialmente ver todas las opciones del compilador de asm y el linker.
Y finalmente no tengo la menor idea como probarlo xD. Tengo el GDB del gcc, pero NI NI NI idea como funciona, los comandos, etc. Acepto sugerencias aca.
Título: Re: PIC18 y sus misterios
Publicado por: Miquel_S en 07 de Octubre de 2015, 09:57:10
Gracias de nuevo ya lo encontré  :-/

Saludos!
Título: Re: PIC18 y sus misterios
Publicado por: yair_xiox en 07 de Octubre de 2015, 12:19:45
hola killer, podrías poner algo de un pic18 comunicándose con un sensor bluethoot como el hc-06 y como seria el envió de caracteres asci, para que quede funcionando la comunicación entre el sensor y el micro 
Título: Re: PIC18 y sus misterios
Publicado por: RALF2 en 07 de Octubre de 2015, 13:59:19
Muy buena y nutrida información, lo que me genero muchas dudas  :(
Primero no entiendo como funciona bien lo del linker  :oops:
El cblock, porque no debe utilizarse?, sera porque solo sirve para declarar constantes que luego no pueden ser modificadas en el programa?
No soy experto en asm, de hecho llevo años que no lo toco solo conozco lo basico de la serie pic16xxxx.
Ahora bien ando un poco atareado estos dias, asi que voy a leer bien todo para poder hacer mis preguntas que las tengo jijji.
Otra cocita:
Citar
    ; Udata - Data no inicializada
    ; Comienza en 0x60 si es que no coloco una direccion
    ; Lo acomoda solo el linker, basta de renegar con CBLOCKS
Bank0:   udata  0x66
V1:   res   1
V2:   res   1
V3:   res   1
No deberia comensar en 0x66 en vez de 0x66?

Y como un aporte mio a lo que coloco el amigo KILLERJC (no le podia dejar todo el trabajo a el  :mrgreen:)
Les coloco esto (https://www.youtube.com/watch?v=rpeyJaa0oBQ), que aclara algunas cosas hechas por el amigo  ;-)

Saludos
Título: Re: PIC18 y sus misterios
Publicado por: Miquel_S en 07 de Octubre de 2015, 15:44:19
Muy buena y nutrida información, lo que me genero muchas dudas  :(
Primero no entiendo como funciona bien lo del linker  :oops:
El cblock, porque no debe utilizarse?, sera porque solo sirve para declarar constantes que luego no pueden ser modificadas en el programa?
No soy experto en asm, de hecho llevo años que no lo toco solo conozco lo basico de la serie pic16xxxx.
Ahora bien ando un poco atareado estos dias, asi que voy a leer bien todo para poder hacer mis preguntas que las tengo jijji.
Otra cocita:
Citar
    ; Udata - Data no inicializada
    ; Comienza en 0x60 si es que no coloco una direccion
    ; Lo acomoda solo el linker, basta de renegar con CBLOCKS
Bank0:   udata  0x66
V1:   res   1
V2:   res   1
V3:   res   1
No deberia comensar en 0x66 en vez de 0x66?

Y como un aporte mio a lo que coloco el amigo KILLERJC (no le podia dejar todo el trabajo a el  :mrgreen:)
Les coloco esto (https://www.youtube.com/watch?v=rpeyJaa0oBQ), que aclara algunas cosas hechas por el amigo  ;-)

Saludos
Hola RALF2 por lo que yo entiendo el Banco 0  empieza en la posición 060h y termina en la 0FFh y el con udata 0x66 le esta diciendo que posicione la variable V1 en la posición 0x66
Título: Re: PIC18 y sus misterios
Publicado por: Miquel_S en 07 de Octubre de 2015, 16:09:21
Hay una cosa que no entiendo, o hay un error cuando declaras las variables
Código: ASM
  1. ; Solo PIC18
  2.    ; Udata - Data no inicializada
  3.    ; Access data
  4.    ; Ubicacion: 0x00 a 0x5F
  5.     udata_acs
  6. Var1:   res     1
  7. Var2:   res     1
  8. Buff:   res     8
le estas diciendo que se posiciona Var1 en 0x00, Var2 0x01 y Buff 0x02 pero aquí estas diciendo que Buff empieza en 0x03 ¿No deberia de ser 0x02 y termina en 0x09?
Código: ASM
  1. Nombre  Direccion
  2.  
  3. Var1    0x00
  4. Var2    0x01
  5. Buff    0x03-0x08
  6. V1      0x89
  7. V2      0x8A
  8. V3      0x8B
  9. BVar1   0x500
  10. BVar2   0x501
  11. BVar3   0x502
lo mismo ocurre con V1:
Código: ASM
  1. Bank0:  udata  0x66
  2. V1:     res     1
  3. V2:     res     1
  4. V3:     res     1
Título: Re: PIC18 y sus misterios
Publicado por: KILLERJC en 07 de Octubre de 2015, 19:40:32
Les pido perdon es que cambie el programa mientras lo iba haciendo. voy a responderles y luego arreglarlo

Miguel

Citar
le estas diciendo que se posiciona Var1 en 0x00, Var2 0x01 y Buff 0x02 pero aquí estas diciendo que Buff empieza en 0x03 ¿No deberia de ser 0x02 y termina en 0x09?
Este es un error mio, habia puesto 4 variables en cada seccion, y encima solo uso 1. resulto que tenia Var1,Var2,Var3 y Buff, luego borre, pero me olvide cambiarle eso, como todas las demas variables como V4 y BVar4 estaban al ultimo no tuve problemas con los otros. Pero ese se me salto.
Buff deberia comenzar en 0x02 y terminar en 0x09 como bien decis.
Para direccionarlo a lo demas ahces Buff+1, Buff+3,Buff+n

Citar
lo mismo ocurre con V1:
Otro de mis cambios en el medio del programa para ver si realmente ocurria, elegi primero el 0x66 por que vi un SFR en 0xF66 resulto luego que ese registro no se puede escribir, y termine buscando otro. el cual es el LATx que comienzan de 0x89, crei haber cambiado todos los valores. Como es un pedazo de texto un poquito grande.. se me paso realmente.

Ya corrijo esos errores, asi no causan mas confusion.
EDIT: Creo que estan todos corregidos


RALF

Citar
Muy buena y nutrida información, lo que me genero muchas dudas  Sad
Primero no entiendo como funciona bien lo del linker  Embarassed
El cblock, porque no debe utilizarse?, sera porque solo sirve para declarar constantes que luego no pueden ser modificadas en el programa?
No soy experto en asm, de hecho llevo años que no lo toco solo conozco lo basico de la serie pic16xxxx.
Ahora bien ando un poco atareado estos dias, asi que voy a leer bien todo para poder hacer mis preguntas que las tengo jijji.
Otra cocita:
No deberia comensar en 0x60 en vez de 0x66?

Vamos por parte, contesto la ultima pregunta.
Cuando estas con el set de instrucciones standard ( y que seguro NO vas a cambiarlo pero ahi es donde reside la diferencia ) para el linker la memoria de 0x00 a 0xFF se encuentra dividida en 2 partes, una que le llama ACCESSBANK y  otra que le llama DATABANK.
ACCESSBANK utilizaria las posiciones de memoria 0x00 a 0x5F
y el DATABANK ( banco 0 )  comienza en 0x60 y termina en 0xFF

Ya voy a explicar lo del linker.
Primero que nada fue un error mio poner 0x66 como bien le respondi a Miguel antes, mi idea era poner variables en memoria que comenzaran en 0x89, yo cambie el programa pero me olvide de cambiar unas partes del texto.
Entonces con ese udata le digo al linker que quiero que todo lo que reserve ahi se ubique en la posicion 0x89, a pesar que comienza en 0x60 para el linker ese pedazo de memoria.

Antes de continuar parece que el linker necesita un poco de explicacion.
Vos tenes un compilador. En este caso es el mpasm , este compilador lo que hace es trasformar tu archivo assembler, uno por uno, en un codigo objeto. Es un codigo objecto por cada archivo. Entonces ¿como se arma el codigo maquina que va en el PIC cuando tengo 2 archivos?. Esto lo hace el linker. El linker comienza a ver todos los archivos y suponete que tenes esto:

Código: ASM
  1. Archivo1:    udata_acs
  2. Var1:   res     1
  3. Var2:   res     1
  4. Buff:   res     8
  5.  
  6. Archivo2:    udata_acs
  7. Var5:   res     1
  8. Var4:   res     1
  9. Buff1:  res     8
(Estarian separado en cada archivo solo lo junto para que quede compacto)

El linker recibe esos codigos objectos y por ejemplo lee el primer archivo... mmm el compilador me dice que debo "reservar" 3 variables (ademas de eso crea "simbolos" para indicarle el nombre al linker) y que ocupan 10 bytes y estan en el accessbank.
Entonces el linker busca en su archivo de linker y observa que ACCESSBANK ocupa de 0x00 a 0x5F.  Como no tiene direccion de inicio lo pone apenas comienza de 0x00 a 0x09, y guarda para el mismo como un "puntero" al ACCESSBANK. listo! ya ubicamos el primer archivo, ahora debemos ir por el segundo, cuando lee el segundo, de nuevo otra ves el compilador le dice que debe reservar otros 10! y en el access bank, para eso el muy picaron ya sabe donde comienza y donde termina el ACCESSBANK por que ya lo leyo, y sabe de donde tiene que poner los datos, por ese "puntero" que guardo. Usa ese "puntero" para comenzar de 0x0A a 0x13, Si por alguna razon tuvo muchas variables y se excedio pasandose del 0x5F, el linker va a tirar un error, y va a decirte: Es imposible meter esta cantidad de datos en ACCESSBANK, por que vos estas usando 0x80 de datos y el largo es de 0x5F nomas.

De la misma forma funciona el codigo.
Si vos tenes varios archivos no hace falta incluir TODOS. simplemente si observas yo puse: la directiva code y no org. Si hago asi para todos los archivos ASM que tenga, no necesito incluirlos para nada. El linker va a comenzar por uno por ejemplo el main, va a ver cuanta memoria posee con el archivo del linker, va a ver que rango de memoria peude usar, seria imposible que vos hagas un 0xFFFF cuando la memoria solo alcanza hasta 0x1FFF por ejemplo, y el linker te acusa,
Comienza por un archivo, y el compilador ASM le indico con sus ORG y CODE que parte es codigo y donde esta ubicado. El linker comienza a armar esto en la fhas, pone X cosa en un lugar, pone Y cosa en otro lugar. Y termine mi archivo, nuevamente guardo un "puntero" de la direccion del final del archivo, cuando viene el otro archivo, comienza a llenar desde ese puntero.

Y no hice ningun include!. El include podrias verlo como copiar todo el otro archivo en uno solo. Que se hace para mayor simplicidad. ( no es una copia exactamente hablando, pero es para que veas la direferencia )
Pero ahora sin ningun include, como es que podes llamar a la funcion de otro archivo? Clasico de un delay.
Para eso el compilador crea simbolos ( estos simbolos luego lo utiliza el linker ) para que se unan. Ejemplo:

main.s
Código: ASM
  1. .extern  _Delay1ms
  2.  
  3.    CALL _Delay1ms

Delay.s
Código: ASM
  1. .global  _Delay1ms
  2.  
  3. _Delay1ms:
  4.             ;Aca codigo delay
  5.             RETURN

Aqui lo que hago es decirle primero al compilador que cree un simbolo _Delay1ms, con extern le digo que ese simbolo proviene de otro archivo. y con .global le dige que ese simbolo esta para que lo usen los demas archivos.
Luego el linker observa ambos archivos  y conoce que desde main.s se llama a _Delay1ms del otro archivo. Como el linker es el que pone los pedazos de codigo a su gusto. Una ves que ubica el codigo en las flash ( supongamos que a Delay1ms lo puso en la posicion de la FLASH 0xF0, transforma por si solo ese simbolo _Delay1ms del CALL en un CALL 0xF0, sin tu intervencion.

Podras observar una cosa, y es que NADA te garantiza cual archivo es el que va a tomar primero el linker, si va a respetar las posiciones de memoria de codigo y datos que le des, si no hay direccion asignada los va a acomodar como el quiera. Entonces vos no podes saber si en 0x00 va a estar Var1 o Var5, pero esto a vos no te importa!, por que cuando haces una instruccion con ese Var1, el linker sabe donde lo ubico y reemplaza ese Var1 por la direccion del mismo. ESTA es la diferencia de un codigo que se amolda solo (rellocatable) y uno absoluto ( en el que vos controlas valor por valor la posicion de memoria flash y la de datos ).

CBLOCK es absoluto. Y ese es uno de los problemas cuando tenes varios archivos, como ves en el ejemplo de arriba que el linker es el que me posiciona las variables a su gusto y luego las "linkea" las une con sus nombres en las instrucciones, en el caso de CBLOCK esto no pasa. Y cuando agregas variables simplemente tenes que saber que posicion ocupan Fue el caso de tener 2 archivos con un CBLOCK que comienza en 0x20 por ejemplo.

Otra cosa tambien es que con CBLOCK vos sos el que tiene el poder de seleccionar la posicion. Si haces un

CBLOCK 0x5E
Var1 ;0x5E
Var2 ;0x5F
Var3 ;0x60
ENDC

cuando hagas un ADDWF VAR3,F,ACCESS no va a funcionar. Por que la direccion es 0x60 y va a intentar escribir los SFR y no la direccion 0x60 de memoria de datos. Pero una cosa mas, NADIE pero NADIE ( linker , compilador ) te lo va a acusar que te pasaste, que estas escribiendo una posicion de memoria que no debes,etc , por que el linker no sabe que eso son "variables" son solo constantes que se van a reemplazar el programa. Voy a intentar crear un ejemplo en el que se use un ADDWF Var2,F,ACCCESS y vemos la diferencia a la salida del compilador


Con CBLOCK el ADDWF quedaria algo asi (obviamente esto ya esta compilado y se pierden los nemonicos, pero es para el ejemplo )

ADDWF 0x5F,F,ACCESS

Sin CBLOCK y con udata_acs:

ADDWF <simboloDeVar2>,F,ACCESS

Luego el linker cuando posiciona Var2 por que esta definido en udata_acs reemplaza la direccion alli (los ultimos 8 bits en este caso obviamente)

Y aqui va la pregunta...
¿Debo o no usar CBLOCK ?

Para un codigo simple no es problema. Pero te fuiste a otro PIC y tal ves cambio todo eso. O si tenes muchos archivos con variables en cada uno, ejemplo LCD,Delays,RS232,main, cada uno con un CBLOCK y si, es un dolor de cabeza a no ser que tires valores grandes y que quede espacio entre los CBLOCKs para ahorrarte ese dolor de reacomodar todo.
Nuevamente con CBLOCK al ser vos el que posiciona las variables sos vos el encargado de revisar que esten bien, que no se "sobrepongan". Esto es un codigo absoluto.

Ahora voy a aclarar una cosa, por ahi dije que para el linker el banco 0 esta dividido en 2, Y eso es verdad, Realmente el banco 0 es un pedazo de memoria de 0x00 a 0xFF, eso se puede ver cuando hicimos una instruccion con BANKED y la direccion era menor a 0x5F ( estando seleccionado el banco 0 obviamente ), pero se crea una "regla" en el archivo del linker diciendo que esta separada en 2, sino el linker podria creer que todo el banco 0 es accesible como ACCESSBANK y ubicar variables que pasen los 0x5F de memoria. y luego en el programa falle. Con esa regla (archivo) limitamos al linker a posicionar las variables en esa porcion de memoria nomas. La cuales traen las ventajas de avisarnos cuando lo superamos ( que no entran mas) despreocuparnos por donde van. etc.

Espero lograr hacerte entender lo que hace el linker, obviamente es mas complicado, como que se crean tablas de simbolos, simbolos localres, tablas de secciones con cada uno su puntero etc etc etc.
Haber en C y no en ASM.... cuando uno hace un extern variable; es lo mismo que aca, es decirle al linker que tiene que unirlo con la variable definida en otro archivo. Como ves el linker/compilador funciona de la misma forma que aca. Solo cambiamos el compilador de uno de ASM por uno de C.
Título: Re: PIC18 y sus misterios
Publicado por: RALF2 en 07 de Octubre de 2015, 20:20:41
Veamos a ver sino estoy equivocado:

Citar
Hola RALF2 por lo que yo entiendo el Banco 0  empieza en la posición 060h y termina en la 0FFh y el con udata 0x66 le esta diciendo que posicione la variable V1 en la posición 0x66

El banco 0 va de 0x000 a 0x0FF, pero en lo que respecta al access bank se utiliza los bytes que van desde 0x000 a 0x05F, la posicion 0x061 corresponderia a banco 0 tambien, pero para poder acceder a ella hay que utilizar el bank select (pag. 66 del data sheet).
Título: Re: PIC18 y sus misterios
Publicado por: KILLERJC en 07 de Octubre de 2015, 20:50:38
Veamos a ver sino estoy equivocado:

Citar
Hola RALF2 por lo que yo entiendo el Banco 0  empieza en la posición 060h y termina en la 0FFh y el con udata 0x66 le esta diciendo que posicione la variable V1 en la posición 0x66

El banco 0 va de 0x000 a 0x0FF, pero en lo que respecta al access bank se utiliza los bytes que van desde 0x000 a 0x05F, la posicion 0x061 corresponderia a banco 0 tambien, pero para poder acceder a ella hay que utilizar el bank select (pag. 66 del data sheet).

Respondi arriba, estaba editandolo. Te respondo:

El banco 0 realmente comienza en 0x00 y termina en 0xFF
Lo que se puede acceder cuando en el opcode es access es de 0x00 a 0x5F
Si queres acceder a memorias 0x60 a 0xFF tenes que usar acceso indirecto o por el BANKED, usando el registro BSR formando la direccion completa BSR:Direccion ( 12 bits )
La separacion de 0x00 a 0x5F como access bank y 0x60 a 0xFF es imaginara del linker. Es para limitar las variables que vaya a poner en esas posiciones de memoria, asi sabe que si intentas poner 0x80 bytes ahi va a saltar un error por que el largo es de 0x5F nomas.
En resumen es para que el linker se maneje.
Título: Re: PIC18 y sus misterios
Publicado por: KILLERJC en 08 de Octubre de 2015, 01:39:32
En una respuesta a RALF LINK (http://www.todopic.com.ar/foros/index.php?topic=45254.msg376624#msg376624)

Lo que sigue a continuacion no tiene NADA que ver con PIC18, ni con ASM, sino con el proceso de compilacion.

Hable sobre que como el compilador genere un .o y luego el linker los une, pero esto es un invento hasta que no se demuestre obviamente.
Para demostrar masomenos que eso realmente ocurre observamos la salida de la consola del MPLAB:

Compilacion con el mpasmx del archivo configuracion.asm , genera 3 archivos, object ( .o ), listing ( .lst ) y error ( .err )

Código: [Seleccionar]
"/opt/microchip/mplabx/v3.10/mpasmx/mpasmx" -q -p18f2550 -u -l\"build/default/production/configuration.lst\" -e\"build/default/production/configuration.err\" -y -o\"build/default/production/configuration.o\" \"configuration.asm\"
Compilacion con el mpasmx del archivo main.asm , genera 3 archivos, object ( .o ), listing ( .lst ) y error ( .err ) , el listing y error son para el usuario

Código: [Seleccionar]
"/opt/microchip/mplabx/v3.10/mpasmx/mpasmx" -q -p18f2550 -u -l\"build/default/production/main.lst\" -e\"build/default/production/main.err\" -y -o\"build/default/production/main.o\" \"main.asm\"
Finalmente Linkeamos con el mplink,

Entradas: el archivo linker ( .lkr ) opciones como _EXTENDEDMODE (indica que tengo activo el set extendido) y que use el main.o y configuration.o creado antes
Salidas: el .map que indica cuanto ocupan cada espacio y como se distribuyo la memoria, y el .cof que ya es el archivo compilado

Código: [Seleccionar]
"/opt/microchip/mplabx/v3.10/mpasmx/mplink"  "/opt/microchip/mplabx/v3.10/mpasmx/LKR/18f2550_g.lkr"  -p18f2550  -w  -m"dist/default/production/PIC18asm.X.production.map" -u_EXTENDEDMODE  -z__MPLAB_BUILD=1  -odist/default/production/PIC18asm.X.production.cof  build/default/production/main.o build/default/production/configuration.o
Finalmente, llama a otro ejecutable que transforma el .cof en un .hex , lo traduce de un formato a otro. este es el mp2hex

Código: [Seleccionar]
MP2HEX 5.08, COFF to HEX File Converter
Copyright (c) 1998-2011 Microchip Technology Inc.
Errors    : 0

Y aqui queda demostrado que eso ocurre! realmente OCURRE!,

Compilador

Para seguir investigando vamos a crear un simple proyecto con 2 archivos, vamos a llamar de un archivo a otro, vamos a usar variables definidas en un lado y en otro. Y vamos a ver los resultados que obtenemos, finalmente ver como queda posicionado en memoria TODO esto.

Para esto creamos 2 archivos, que llame: main.s y auxiliar.s , estos archivos estan simplificados al maximo. Es decir no tiene codigo para configurar los modulos, no inclui el .inc para hacer mas visible esto, ni nada por el estilo. Tienen muy pocas intrucciones tambien.

Aqui dejo los 2 archivos:

main.s ( si, no posee include, lo saque a proposito y no deben agregarlo para que funcione )

Código: ASM
  1. ;************************************************    
  2. ;   Definicion de variables
  3. ;************************************************    
  4.  
  5.         ; Externo lo de afuera, y global para que los demas lo vean
  6.         global  Var1
  7.         extern  _Suma, Var3
  8.    
  9. Bank0:  udata_acs
  10. Var1:   res     1
  11. Var2:   res     1
  12.        
  13. ;************************************************    
  14. ;   Vectores de reset e interrupcion
  15. ;************************************************    
  16.    
  17. Rst:    code    0x00    ;Vector de Reset
  18.         GOTO    Main
  19.    
  20.         org    0x08     ;Vector de Interrupcion Alta Prioridad
  21.         RETURN
  22.    
  23.         org    0x18     ;Vector de Interrupcion Baja Prioridad
  24.         RETURN
  25.  
  26. ;************************************************    
  27. ;   Programa Principal
  28. ;************************************************    
  29.    
  30. Main:
  31.     CALL    _Suma
  32.     NOP
  33.     MOVLW   0x78
  34.     IORWF   Var3
  35.     NOP
  36.     GOTO    $           ;Loop infinito
  37.  
  38. ;----------- Fin de programa ---------------------        
  39.     END

auxiliar.asm

Código: ASM
  1. ;************************************************    
  2. ;   Mas variables, 1 mas y definiciones
  3. ;************************************************
  4.  
  5.         ; Externo lo de afuera, y global para que los demas lo vean
  6.         extern  Var1
  7.         global  _Suma, Var3
  8.        
  9.         udata_acs
  10. Var3:   res     1
  11.  
  12.        
  13. ;************************************************    
  14. ;   CODIGOOOOOOOOOOOOOOOOOO
  15. ;************************************************      
  16.         code
  17.        
  18. _Suma:
  19.         MOVLW   0x10
  20.         ADDWF   Var1
  21.         RETURN
  22.        
  23.        
  24. ; Fin del archivo      
  25.        
  26.         END

OK compilamos y..... TODO PERFECTO!
Probamos nuestro codigo. Este comienza en el vector de reset, va al Main, entra en el CALL y se ejecuta _Suma del otro archivo, modifica la variable que esta definida en el primer archivo, vuelve y ahi desde el main.s modifico la variable definida en el auxiliar.
Y lo que es peor funciona! .. Lo pueden simular

Antes dijimos que el linker va a acomodar el programa donde MAS le guste, va a posicionar las variables como le guste si es que no especificamos una direccion concreta.
Vamos a la memoria de programa y tenemos esto:

Código: [Seleccionar]
     Line     Address       Opcode           Label                       DisAssy               
        1  0000          EF0D                              GOTO 0x1A                           
        2  0002          F000                              NOP                                 
        3  0004          0000                              NOP                                 
        4  0006          FFFF                              NOP                                 
        5  0008          0012                              RETURN 0                             
        6  000A          0E10         _Suma                MOVLW 0x10                           
        7  000C          2600                              ADDWF Var1, F, ACCESS               
        8  000E          0012                              RETURN 0                             
        9  0010          FFFF                              NOP                                 
       10  0012          FFFF                              NOP                                 
       11  0014          FFFF                              NOP                                 
       12  0016          FFFF                              NOP                                 
       13  0018          0012                              RETURN 0                             
       14  001A          EC05         Main                 CALL 0xA, 0                         
       15  001C          F000                              NOP                                 
       16  001E          0000                              NOP                                 
       17  0020          0E78                              MOVLW 0x78                           
       18  0022          1202                              IORWF Var3, F, ACCESS               
       19  0024          0000                              NOP                                 
       20  0026          EF13         _.org_1_0026         GOTO 0x26

Veamos como estan ubicados. Los vectores de reset e interrupcion estan en sus correspondientes lugares como se pidio. (0x0 , 0x8 y 0x18), El Main sigue luego del vector de interrupcion, esto es obvio por que eso pedimos. Dijimos con el "org" esto va a partir de ACA (0x18). Y _Suma ???? Como era tan pequeño y entraba entre los vectores de interrupcion el linker decidio ponerlo ahi!. Es decir el linker acomodo solo la seccion de codigo, hasta aprovechando el espacio en este caso. ¿Esto va a ocurrir siempre?, no esto no ocurre siempre asi. Pero aca se puede ver como es el linker quien toma los 2 archivos, y los une en uno solo sin necesidad de includes. Ahora veamos la memoria de datos:

Código: [Seleccionar]
    Address      Symbol      Hex     Decimal        Binary       Char 
000           Var1        0x00    0            00000000        '.'     
001           Var2        0x00    0            00000000        '.'     
002           Var3        0x00    0            00000000        '.'     

El linker me acomodo las secciones de datos de cada archivo ( access ) como a el le gusto. Y todo esto:

- Sin indicar direcciones ( a excepcion de los vectores de reset/interrupcion )
- Sin includes .. y no me importan donde esta la función (si al final del archivo o no), yo puedo llamarla, solo tengo que decirle: "Esto esta en otro archivo arreglatelas vos linker".

Al comienzo hablamos que el compilador genera varios archivo mas aparte del .o , vamos a build/default/production/ desde la carpeta de nuestro proyecto y... encontramos todos los archivos esos, como todo compilo bien no hay errores, por lo cual main.err y auxiliar.err estan vacios. ahora vamos a ver los listing, este archivo nuevamente repito y remarco lo crea el compilador, y no el linker.

Veamos algunos, y de paso les muestro lo que quiero que vean. Al abrir el archivo al final nos encontramos con esto:

mains.lst
Código: [Seleccionar]
SYMBOL TABLE
  LABEL                             VALUE

Main                              0000001A
Var1                              00000000
Var2                              00000001
Var3                              00000000
_.org_1_0026                      00000026
_Suma                             00000000
__18F2550                         00000001

auxiliar.lst

Código: [Seleccionar]
SYMBOL TABLE
  LABEL                             VALUE

Var1                              00000000
Var3                              00000000
_Suma                             00000000
__18F2550                         00000001

Se ven la tabla de los simbolos, cada archivo posee la suya. Ahi vemos todas las "etiquetas" que creamos y tambien las que difinimos como "externas" es decir que existen (en algun lugar), esto al compilador no le interesa, el solo compila.

Ademas hay un __18F2550 agregado por el compilador, esto no se si les recuerda cuando tiene un archivo para muchos micros y ponen:

Código: [Seleccionar]
ifdef __18F2550
   Hacer algo
endif
ifdef __16F628A
   Hacer otra cosa
endif

Para eso esta :P.
Otra cosa interesante de esto se ve en la parte del codigo dentro de estos lst:

main.lst
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
auxiliar.lst
Código: [Seleccionar]
LOC  OBJECT CODE     LINE SOURCE TEXT
  VALUE

                      00001
                      00002 ;************************************************   
                      00003 ;   Mas variables Wiii
                      00004 ;************************************************
                      00005
                      00006         ; Externo lo de afuera, y global para que los demas lo vean
  0000                00007         extern  Var1
  0000                00008         global  _Suma, Var3
                      00009         
                      00010         udata_acs
000000                00011 Var3:   res     1
                      00012
                      00013         
                      00014 ;************************************************   
                      00015 ;   CODIGOOOOOOOOOOOOOOOOOO
                      00016 ;************************************************       
                      00017         code
                      00018         
000000                00019 _Suma:
000000 0E10           00020         MOVLW   0x10
000002 26??           00021         ADDWF   Var1
000004 0012           00022         RETURN
                      00023         
                      00024         
                      00025 ; Fin del archivo       
                      00026         
                      00027         END

Observen la posicion de cada una de las instrucciones/datos ( es la columna de la izquierda ) , es justamente LOC (Ubicacion) , lo que ven a la derecha de ese numero es el opcode de la instruccion, las directivas tiene LOC 0.
Viendo el main.lst notamos como cuando creamos datos los numera, Var1 ocuparia la posicion de memoria 000000 de datos, Var2 la 000001 de datos, luego cuando comienza el codigo ( code ) el indice cambia y comienza nuevamente de 0, responde a los "org" y va dando la posicion de la flash como si solo de ese archivo se tratase. Esto significa que tiene un "puntero" para datos y un puntero para "programas" o para ser mas correcto es un puntero por seccion.

Luego vamos a nuestro auxiliar.lst y encontramos algo curioso: el dato comienza en 0x00 y no 0x02 ( si recordamos del main) y el codigo tambien. Estarian superponiendose "supuestamente", esto no es asi. Luego el linker va a acomodar todo eso. Ya que como dijimos y vuelvo a repetir, esto al compilador NO le importa, NO es su trabajo.

Nombremos ademas otra cosa, recuerda cual era el opcode de el ADDWF? era asi 0010 01fa xxxx xxxx  (0x26xx con f=1 y a=0)
En este caso f es 1, a es 0 y pero ¿x?. Veran que tiene un 0x26?? , ese opcode no es valido, Ese opcode luego el linker lo va a acomodar cuando proceda a unir todo y reemplaze los simbolos por las posiciones de memoria que les asigno el  linker a esos datos.

Linker

Se vio claramente el tema de los simbolos, como el compilador piensa en un solo archivo a la ves, y luego es el linker quien reune todos estos pedazos. Solo nos queda un solo archivo para ver. Y es lo que devuelve el linker, ademas del .cof que ya conocemos, el linker devuelve un .map, podriamos decirlo como un informe del linker, asi como el .lst es un informe del compilador.

Abrimos el MAP y encontramos:

Primero un informe de las secciones ( lo recorte un poco )

Código: [Seleccionar]
                                 Section Info
                  Section       Type    Address   Location Size(Bytes)
                ---------  ---------  ---------  ---------  ---------
                      Rst       code   0x000000    program   0x000004
                   .cinit    romdata   0x000004    program   0x000002
                   .org_0       code   0x000008    program   0x000002
                    .code       code   0x00000a    program   0x000006
                   .org_1       code   0x000018    program   0x000012
.config_300000_BUILD/DEFAULT/PRODUCTION/CONFIGU    romdata   0x300000    program   0x000001
                  ...........................................................
.config_30000D_BUILD/DEFAULT/PRODUCTION/CONFIGU    romdata   0x30000d    program   0x000001
                    Bank0      udata   0x000000       data   0x000002
               .udata_acs      udata   0x000002       data   0x000001

Veamos que secciones tiene mi linker, pero antes no se si se preguntaron el por que al codigo de _Suma no lo puso luego del vector de reset, si este entraba ahi. Aca hay algunas respuestas. Cada seccion tiene un nombre, a la izquierda vemos cuales son. Rst ( Miren la etiqueta en el programa ) ubicado en el 0x00, en la memoria de programa y de largo 4 bytes. y luego de eso... La seccion .cinit, seccion utilizada por C pero que nuestro linker parece tener ya pre-establecido (Esto evito que _Suma ubique la posicion de comienzo). Luego tenemos los .org que pusimos y el .code de nuestro auxiliar!. Luego de eso esta la lista de fuses. y al ultimo tenemos 2 secciones, si 2, la primera llamada Bank0 y la otra .udata_acs , ¿ pero no lo definimos a los con udata_acs ?, Si pero sin querer agregue la etiqueta Bank0 en el main.s :P. Mientras que auxiliar no tiene nada. , observen ademas que ahi dice donde comienza, el largo y donde se almanena, es decir en la memoria de datos. Si yo no hubiera agregado la etiqueta los hubiera puesto todo dentro de una misma seccion. Lo mismo si antes de la etiqueta Main hubiera puesto "code", esto hubiera hecho que se junte en una sola seccion "code" el codigo de auxiliar ( y ya no entraria mas entre medio de los vectores - Al final pruebo esto )

Siguiendo un poco mas abajo el archivo se puede encontrar las porciones de memoria contiguas llenas de Flash, como que no hay mucho para explicar aca:

Código: [Seleccionar]
                              Program Memory Usage
                               Start         End     
                           ---------   ---------     
                            0x000000    0x000005     
                            0x000008    0x00000f     
                            0x000018    0x000029     
                            0x300000    0x300003     
                            0x300005    0x300006     
                            0x300008    0x30000d     
            44 out of 33048 program addresses used, program memory utilization is 0%

Y finalizando, mas SIMBOLOS!

Código: [Seleccionar]
                            Symbols - Sorted by Name
                   Name    Address   Location    Storage File                     
              ---------  ---------  ---------  --------- ---------               
                   Main   0x00001a    program     static /home/x/workspace/MPLAB/PIC18asm.X/main.asm
           _.org_1_0026   0x000026    program     static /home/x/workspace/MPLAB/PIC18asm.X/main.asm
                  _Suma   0x00000a    program     extern /home/x/workspace/MPLAB/PIC18asm.X/auxiliar.asm
                   Var1   0x000000       data     extern /home/x/workspace/MPLAB/PIC18asm.X/main.asm
                   Var2   0x000001       data     static /home/x/workspace/MPLAB/PIC18asm.X/main.asm
                   Var3   0x000002       data     extern /home/x/workspace/MPLAB/PIC18asm.X/auxiliar.asm


Donde dice la direccion asignada, el nombre, donde se ubican, y si son locales o globales, esto es 1 por cada archivo. Se observa que esas variables que declaramos globales estan como extern y las que son solamente locales, es decir solo del archivo y no se pueden acceder de otro lado son static.
( ¿ Ahora te suena los modificadores static y extern de C ? )

-----------------------------------
Probando mas cosas

Probando unir las secciones. Comente que iba a probar esto y ver como quedaba, lo que hice fue: Quitarle el Bank0: al udata_acs del main.s y antes del Main: le agregue un "code" asi como esta el archivo auxiliar.s, Resumen:

main.s ( Cambios, asi quedaron ahora)
Código: ASM
  1. udata_acs
  2. Var1:   res     1
   
Código: ASM
  1. code
  2. Main:

Simulo:
- Memoria de datos igual.
- Memoria de programa: CAMBIO!, ahora esta todo luego de los vectores, por que ahora es todo un pedazo grande de instrucciones.
- Los archivos .lst perdieron ese simbolo ( Bank0 )
- El .map ahora esta formado por otra cosa:


Código: [Seleccionar]
                  Section       Type    Address   Location Size(Bytes)
                ---------  ---------  ---------  ---------  ---------
                      Rst       code   0x000000    program   0x000004
                   .cinit    romdata   0x000004    program   0x000002
                   .org_0       code   0x000008    program   0x000002
                   .org_1       code   0x000018    program   0x000002
                    .code       code   0x00001a    program   0x000016
.config_300000_BUILD/DEFAULT/PRODUCTION/CONFIGU    romdata   0x300000    program   0x000001
               .udata_acs      udata   0x000000       data   0x000003

Ahora .udata_acs esta todo en una seccion propia, y .code en su propia seccion, conteniendo a ambos codigo de los 2 archivos. Como ahora la seccion ".code" era muy grande no entro entre medio de los vectores. Y el linker jamas puede poner un GOTO por el mismo para aprovechar eso. Tampoco lo podria dividir ya que sino alteraria el programa.


Error de linker - Simbolo faltante
Bueno ya probe esto, ahora quiero ver si le meto un error, Voy a comentar el global a un archivo y ver que sucede

Comente la linea "global Var1" en el main.s, asi de esa forma no se crea el simbolo y auxiliar.s no tiene donde unirse y obtengo un error:

Código: [Seleccionar]
make[2]: *** [dist/default/production/PIC18asm.X.production.hex] Error 1
make[1]: *** [.build-conf] Error 2
make: *** [.build-impl] Error 2

MPLINK 5.08, LINKER
Error - could not find definition of symbol 'Var1' in file 'build/default/production/auxiliar.o'.
Errors    : 1

¿De quien es ese error?, parece del linker, la cultura popular dira que es del compilador, ya que este hace todo. Si voy a los archivos main.err y auxiliar.err veo y ..... NADA, vacios!, claramente al compilador le importa poco si existen o no por fuera del archivo xD, solo el linker quien es el encargado de unir las cosas.

Error de linker - Memoria Fuera de rango
(Esto no es la idea de ponerle una direccion, realmente si vamos a hacer un codigo que el linker lo acomode solo no deberiamos poner direcciones)

A mi main lo vuelvo al original y le hago un cambio mas:

Código: ASM
  1. Bank0:          udata_acs 0x5F
  2. Var1:   res     1
  3. Var2:   res     1
(Aclarar que el Bank0 esta ahi asi creo otra seccion, como se vio en el map)

Con CBLOCK Var1 se definiria como 0x5F y Var2 como 0x60 sin problemas.
Si yo compilo asi, termino con esto:

Código: [Seleccionar]
Error - section 'Bank0' can not fit the absolute section. Section 'Bank0' start=0x0000005f, length=0x00000002
Errors    : 1

Exacto, no podes alojar eso ahi. ya que esta en el borde y solo hay 1 lugar, nuevamente los .err generados por el compilador estan vacios.

Error del compilador - Mala instruccion
Y ya que estamos por curiosodad, veamos que sale de un archivo .err
Volvemos al original y le cambie el IORWF Var3 por IOXWF Var3

Miramos la consola y vemos los errores:

Compilador:
Código: [Seleccionar]
Warning[207] /home/fabian/workspace/MPLAB/PIC18asm.X/main.asm 34 : Found label after column 1. (IOXWF)
Error[122]   /home/fabian/workspace/MPLAB/PIC18asm.X/main.asm 34 : Illegal opcode (Var3)

Linker:
Código: [Seleccionar]
Error - Error reading object file 'build/default/production/main.o'
Errors    : 1

El compilador que no entiende nada y el linker que no encontro los archivos .o por que se suspendio todo y no se generaron, ahora voy al .err y tengo lo mismo que me dio por la consola:

Código: [Seleccionar]
Warning[207] /home/fabian/workspace/MPLAB/PIC18asm.X/main.asm 34 : Found label after column 1. (IOXWF)
Error[122]   /home/fabian/workspace/MPLAB/PIC18asm.X/main.asm 34 : Illegal opcode (Var3)

Bueno esto es todo, un lindo paseo por las herramientos y la compilacion, si alguna ves leyeron de listing, map entre otras opciones en C, es realmente esto.
El compilador C ( mejor dicho su ejecutable ) puede llegar a hacer todo en un solo paso y no en 2 como hice al comienzo, este seria un caso bastante especial, pero por dentro ( internamente) estan divididos asi como esta explicado, el compilador C funciona como el de ASM, va  crear varias secciones de la misma forma, nomas que estas ya tienen un nombre particular como .text , .data y .bss .
Por eso mucho no me queria meter aca con esto xD, ya que esto es programacion general y no solo de PIC18, en fin, espero no haber dicho cualquier barbaridad y haber demostrado algo. Estoy seguro que hay gente que me supera en conocimientos por mucho, y seguro que algun defecto le va a encontrar, pero esto es hasta lo que yo se.
Título: Re:PIC18 y sus misterios
Publicado por: Miquel_S en 09 de Octubre de 2015, 12:06:55
Gracias de nuevo KILLERJC, estoy aprendiendo un montón y espero poder seguir aprendiendo.

Miquel_S
Título: Re:PIC18 y sus misterios
Publicado por: KILLERJC en 09 de Octubre de 2015, 17:09:34
Ya saben como va el post, cualquier cosa pidan, si lo se voy a intentar decirlo como es.
Ahi voy a hacer un codigo para que envie datos por la UART y reciba por interrupcion para yair_xiox , mas que obvio es que va a ser un solo dato y recibir un dato, lo que haga con el dato luego es tema de el.
Mejor aun ahora que lo pienso voy a hacer un loop. es decir, lo recibido lo envio de vuelta
Título: Re:PIC18 y sus misterios
Publicado por: yair_xiox en 09 de Octubre de 2015, 17:16:44
gracias killer, igual en el trabajo no me dejan programar en asembler todo es en c
Título: Re:PIC18 y sus misterios
Publicado por: yair_xiox en 09 de Octubre de 2015, 17:19:45
oye killer puedes poner un programa con un pic18 para que se comunique con cualquier modulo bluethoot  y lo de mandar los caracteres asci
Título: Re:PIC18 y sus misterios
Publicado por: KILLERJC en 09 de Octubre de 2015, 17:35:25
oye killer puedes poner un programa con un pic18 para que se comunique con cualquier modulo bluethoot  y lo de mandar los caracteres asci

Enviar caracteres ASCII puede ser. Comunicarse con cualquier modulo bluetooth es muy general. No voy a hacer un programa que por ejemplo se comunique, configure el HT-05/06 por ejemplo. Solo lo de enviar un dato si, o enviar una cadena de caracteres tambien. Pero ya la comunicacion completa es del usuario. Ya que son muchos comandos AT que hay, la forma en especial que quiera hacerlo,etc. Pero vas a tener un comienzo.

gracias killer, igual en el trabajo no me dejan programar en asembler todo es en c

Lo que puse ahi no tiene nada que ver casi con ASM (aunque este escrito los ejemplos para MPASM), al menos lo ultimo sobre le linker/compilador, es funcionamiento comun de casi todos los compiladores C (que en un bin traen todo, compilador C, ASM y linker). Debes entender eso ya que de igual manera se maneja C. Si no me crees compila un proyecto C con 2 archivos y vas a verlo, en las opciones podes agregar que muestre el archivo .lst y de como resultado el .map.
Título: Re:PIC18 y sus misterios
Publicado por: KILLERJC en 10 de Octubre de 2015, 01:10:48
A pedido de yair un codigo para enviar el comando "AT+RST" por UART, en el que se puede ver ademas el uso de las tablas para leer la memoria flash y el guardar string en la misma.

Código: ASM
  1. list
  2.         include "p18f2550.inc"
  3.        
  4. ;************************************************    
  5. ;   Vectores de reset e interrupcion
  6. ;************************************************    
  7.    
  8.         org    0x00     ;Vector de Reset
  9.         GOTO    Configuracion
  10.    
  11.         org    0x08     ;Vector de Interrupcion Alta Prioridad
  12.         RETURN
  13.    
  14.         org    0x18     ;Vector de Interrupcion Baja Prioridad
  15.         RETURN
  16.  
  17. ;************************************************    
  18. ;   Programa Principal
  19. ;************************************************    
  20.  
  21. ; Comienzo de la seccion code
  22.        
  23.         code
  24.  
  25. ; Creacion de datos en la memoria de programa, dentro de la seccion .code (memoria de programa)
  26. ; Podria haber creado una seccion y puesto en otro lado fijo, pero aqui no me importa :P
  27.  
  28. AT_COM1:    dw "AT+RST",00
  29.        
  30. Configuracion:
  31.  
  32.         ; Configuracion modulo UART, segun datasheet
  33.        
  34.         MOVLW   0xC0    ; 1100 0000
  35.         MOVWF   TRISC
  36.         ; 115200 baudios a un cristal de 40Mhz
  37.         CLRF    SPBRGH
  38.         MOVLW   0x56
  39.         MOVWF   SPBRG
  40.         BSF     BAUDCON,BRG16
  41.         BCF     TXSTA,SYNC
  42.         BSF     RCSTA,SPEN
  43.         BSF     TXSTA,TXEN
  44.  
  45. Main:
  46.         MOVLW   UPPER AT_COM1   ; Cargo el valor de la tabla
  47.         MOVWF   TBLPTRU         ; Asi leo de la memoria de programa
  48.         MOVLW   HIGH AT_COM1
  49.         MOVWF   TBLPTRH
  50.         MOVLW   LOW AT_COM1
  51.         MOVWF   TBLPTRL
  52.        
  53.         CALL    Enviar
  54.  
  55. Fin:                            ; Termino de enviar todo, espero.
  56.         GOTO    $               ; Loop infinito
  57.  
  58.        
  59.  
  60. ; Funcion que envia por UART, el contenido indicado por la tabla.      
  61.        
  62. Enviar:
  63.         TBLRD*+                 ; Leo y aumento el puntero
  64.         MOVF    TABLAT,W        ; Me aseguro que no sea 0, con 0 se termino el string
  65.         BTFSC   STATUS,Z        ; Es 0 salgo.
  66.         RETURN
  67.         MOVWF   TXREG           ; Envio
  68. Espero: BTFSS   TXSTA,TRMT      ; Me aseguro que termino antes de enviar otro
  69.         GOTO    Espero          ;
  70.         GOTO    Enviar          ; Esta libre? Envio otro
  71.        
  72.        
  73. ;----------- Fin de programa ---------------------        
  74.     END

Se denota que la funcion Enviar se puede utilizar para varias string, solo hay que definirlas, cargar la base de las mismas y se envian. incluso se puede crear otra seccion que solo contenta esos string, asi solo se necesita modificar por ejemplo la parte baja del apuntador de las tablas y no los 3 registros.

Loop de la UART, lo recibido es nuevamente enviado:

Código: ASM
  1. list
  2.         include "p18f2550.inc"
  3.        
  4. ;************************************************    
  5. ;   Vectores de reset e interrupcion
  6. ;************************************************    
  7.    
  8.         org    0x00     ;Vector de Reset
  9.         GOTO    Configuracion
  10.    
  11.         org    0x08     ;Vector de Interrupcion Alta Prioridad
  12.         GOTO    Interrupcion
  13.    
  14.         org    0x18     ;Vector de Interrupcion Baja Prioridad
  15.         RETURN
  16.  
  17. ;************************************************    
  18. ;   Programa Principal
  19. ;************************************************    
  20.  
  21. ; Comienzo de la seccion code
  22.        
  23.         code
  24.        
  25. Configuracion:
  26.  
  27.         ; Configuracion modulo UART, segun datasheet
  28.        
  29.         MOVLW   0xC0    ; 1100 0000
  30.         MOVWF   TRISC
  31.         ; 115200 baudios a un cristal de 40Mhz
  32.         CLRF    SPBRGH
  33.         MOVLW   0x56
  34.         MOVWF   SPBRG
  35.         BSF     BAUDCON,BRG16
  36.         BCF     TXSTA,SYNC
  37.         BSF     RCSTA,SPEN
  38.         BSF     RCSTA,RCEN
  39.         BSF     TXSTA,TXEN
  40.  
  41.         ; Configurando interrupciones
  42.        
  43.         BSF     PIE1,RCIE   ; Habilito interrupciones de recepcion
  44.         BSF     IPR1,RCIP   ; Prioridad alta en RX
  45.         BSF     RCON,IPEN   ; Habilito las prioridades
  46.         BSF     INTCON,GIEH ; Habilito interrupciones de alta prioridad
  47.        
  48. Main:  
  49.         GOTO    Main            ; Loop infinito
  50.  
  51. ; Interrupcion de la UART usando los registros rapidos para tener W y STATUS
  52.        
  53. Interrupcion:
  54.         MOVFF   RCREG,TXREG
  55.         RETFIE  FAST
  56.        
  57. ;----------- Fin de programa ---------------------        
  58.     END

En ese ultimo ejemplo se aprovecha el uso de las interrupciones en el PIC18, el cual al entrar no solo se guarda el PC sino W y STATUS. Para usarlo uno luego debe usar el FAST al final. Esto no es solo para este caso, si que tambien el CALL y RETURN permiten el uso del FAST
Título: Re:PIC18 y sus misterios
Publicado por: Miquel_S en 09 de Noviembre de 2015, 19:04:43
Buenas noches, tengo algunas dudas con las interrupciones de alta y baja prioridad, mi idea es crear una interrupción de baja prioridad en el TMR0 y por lo que veo en la imagen que adjunto mas abajo no veo que necesite del registro IPEN:
(http://www.todopic.com.ar/foros/imgtiny/mwa6jc.png)
pero al mirar esta otra imagen veo que si no pongo a '1' dicho registro no me funcionara la Interrupción ya que al ser una puerta AND todas sus entradas deben de estar a '1' para que su salida sea '1' ¿O soy yo que no lo planteo bien?
(http://www.todopic.com.ar/foros/imgtiny/2wrhgcx.png)

Gracias.
Título: Re:PIC18 y sus misterios
Publicado por: KILLERJC en 09 de Noviembre de 2015, 19:54:29
El primer grafico esta simplificado.

IPEN - habilita o no las prioridades

En el primer grafico ves como funcionaria. Si este estuviera activo no estarian "unidos" la parte de alta prioridad y baja prioridad (serian casi 2 circuitos separados uno de otro). Entonces cada interrupcion posee su prioridad.  Tambien se ve que cuando se activa una de alta prioridad, inhabiita a una de baja.

Ahora mira las prioridades, Cuando tenes un 1 en TMR0IP es de alta prioridad, ya que baja prioridad pone el negado y es un 0. Ahora que ocurre cuando deshabilitas las prioridades con IPEN = 0. Tanto las de alta como las de baja actuan sobre el vector de 0x0008, sea cual sea la prioridad, Ejemplo digamos que tenes un 0 en TMR0IP (baja prioridad si estuviera habilitado) Si ocurre una interrupcion por TMR0IF al estar IPEN en 0 iria a la parte superior y actuaria por el vector 0x0008, si hubiera un 1 en TMR0IP actuaria la parte superior, ademas esto inhabilita el vector 0x018.

Es un diagrama simplificado. Si fuera correcto el diagrama tendrias que al estar desactivada las prioridades, se produciria una condicion de carrera, ya que si se activa primero en la parte inferior el tiempo de propagacion entre compuertas se dispararia primero el vector de abajo (0x0018). Aunque luego la de alta prioridad la inhabilite, pero se estarian ejecutando 2 instrucciones por una misma entrada. Ya que no hay una compuerta AND con IPEN  a la salida de baja prioridad. Puede que no sea problema por la latencia de la interrupcion.

El segundo diagrama muestra algo mas real y completo. Y se observa que en "baja prioridad" es decir la salida al vector 0x0018 se bloquea al tener IPEN en 0. esto es por que cuando las interrupciones tiene deshabilitadas las prioridades, todas son tratadas como si fueran alta prioridad. ( vector en 0x0008 )

Entonces aca tenes que decidir, ¿tu intencion es solamente hacer una interrupcion normal o interrupcion con prioridad?

Si es una interrupcion normal, deja IPEN en 0, y actuarias sobre el vector 0x0008 para todas. ( tal cual hacemos en los PIC16 y su vector 0x0004 )
Si queres prioridad, pones el IPEN en 1, y en caso de ser baja prioridad (TMR0IP = 0 ), actuarias sobre el vector 0x0018
Título: Re:PIC18 y sus misterios
Publicado por: Miquel_S en 10 de Noviembre de 2015, 05:27:25
Entendido y gracias por la explicación, mi intención es usar las prioridades, voy a ver si consigo que me funcione el TMR0 en baja prioridad.

Saludos!
Título: Re:PIC18 y sus misterios
Publicado por: RICHI777 en 10 de Noviembre de 2015, 10:20:02
Siento admiración por la gente que conoce a fondo la arquitectura PIC !!! Para los que venimos de arquitecturas mas ortogonales se nos hace muy difícil entenderla. Y ojo no hablo de mejor o peor sino arquitecturas diferentes.

Saludos !