domingo, 3 de febrero de 2019

Instrucción LPM(Load Program Memory)


La instrucción LPM son las iniciales de "Load Program Memory" que quiere decir que va a cargar en un registro Rd el valor de un byte de dato del Flash Program Memory.

3 maneras de leer dato de program memory a un registro:
  • LPM;                Carga un Byte apuntado por Z a R0.
  • LPM Rn,Z;       Carga un Byte apuntado por Z hacia Rn(R0-R31).
  • LPM Rn,Z+;     Igual que los anteriores pero se incrementa Z despues de cargar el Byte.
Cuando se usa LPM, el registro Z debe contener la dirección de byte de los datos.

>>LPM R16,Z;--->va a cargar a en R16 un dato de flash program memory apuntado por Z.
LPM Instruction
Lo que hace posible que podamos acceder a los 16kword  de direcciones es el PC(Program Counter), por ejemplo nuestro atmega32 tiene un PC de 14 bits, eso significa que podemos acceder a 2^14 direcciones que es equivalente a 16384 direcciones(0--16383)=16k 

En la siguiente imagen se puede observar mejor como funciona la Instrucción LPM.
LPM Instruction
Ejemplo de uso
Ejemplo de uso 2

¿Por qué *2 ó <<1?


Como pueden ver en la primera imagen, la memoria de programa está organizada en words de 16 bit y el bit menos significativo del puntero Z selecciona si se elegirá el byte bajo (0) o el byte alto (1). Según lo anterior tenemos 15 bits para apuntar a cualquier dirección de flash  y 1 bits(LSB) para ELEGIR LA MANERA QUE SE VA A ACCEDER(SEA LA PARTE BAJA O LA PARTE ALTA).
Esta instrucción puede dirigirse a los primeros 2^15 direcciones word = 32768 word= 32KBytes de memoria de programa. 

Para que sepas como se guardan los datos en flash te recomiendo que leas el tutorial que realicé tiempo atrás, su nombre es "Ubicando código en la memoria FLASH-ROM". 
Una vez que ya has leído te darás cuenta como se guarda cada instrucción de código en flash, en la cual se resumen a la manera de guardar opcodes y operandos, cada línea de código son 16 bits y es porque el ancho de la menoría flash es de 16 bits.


En esta primera tabla se muestran los posibles valores que tomará Z(en binario) cuando apunta a N dirección.

Valores de Z(en binario)

Para leer el byte bajo de cada  ubicación de memoria de flash nosotros debemos desplazar la dirección 1 bit a la izquierda y colocar un 0 lógico.
Para leer el byte alto de cada  ubicación de memoria de flash nosotros debemos desplazar la dirección 1 bit a la izquierda y colocar un 1 lógico.
Por ejemplo :
Para acceder al byte bajo de la ubicación 0b0000_0101, debemos de cargar a Z con  0b000_1010.
Para acceder al byte alto de la ubicación  0b0000_0101, debemos de cargar a Z con  0b000_1011.
Para acceder al byte bajo de la ubicación 0b0000_0011, debemos de cargar a Z con  0b000_0110.
Para acceder al byte alto de la ubicación  0b0000_0011, debemos de cargar a Z con  0b000_0111.
En código acceder a la parte baja sería:
                   LDI ZH, HIGH(ADDRESS FLASH<<1)
                                                            LDI ZL,  LOW(ADDRESS FLASH<<1) 
En código acceder a la parte alta sería:
                      LDI ZH, HIGH(ADDRESS FLASH<<1|1)
                                                            LDI ZL,  LOW(ADDRESS FLASH<<1|1) 

La tabla de los posibles valores de Z en valores hexadecimales serían como se muestra en la siguiente imágen:


  • EJEMPLOS:
  • Si queremos apuntar a la parte baja de la dirección flash(16 bits)=0x0002 --> Z =  0x0004. 
  • Si queremos apuntar a la parte alta de la dirección flash(16 bits)=0x0002 -->  Z =  0x0005.
  • Si queremos apuntar a la parte baja de la dirección flash(16 bits)=0x0005 --> Z =  0x000A. 
  • Si queremos apuntar a la parte alta de la dirección flash(16 bits)=0x0005 -->  Z =  0x000B. 

Volvamos a nuestro ejemplo, al momento de cargar la dirección de TABLE se le desplaza 1 bit a la izquierda, con el fin de que LSB sea cero, de esa forma cargo el Byte bajo.
                    LDI ZH, HIGH(TABLE<<1)
                    LDI ZL,  LOW(TABLE<<1)
Por ejemplo si dirección de TABLE es 1111111100000111(16 bits) al desplazar un bit a la izquierda sería 1111111000001110 de esa manera indico que estoy apuntando al Byte bajo para ser leído.
Algunos en vez de desplazar un bit a la izquierda prefieren multiplicarlo *2 que el resultado es el mismo, por ello también es válido haber usado:
                    LDI ZH, HIGH(TABLE*2)
                    LDI ZL,  LOW(TABLE*2)

  • Existe un "puente" entre el bus de datos de la memoria de programa y el bus de datos de la memoria de datos y esto se hace a traves de la instrucción LPM.
  • Para acceder a un byte de la memoria del programa se usa el registro Z, que contendrá su dirección. 
  • El bit 0 del registro Z selecciona el byte alto o bajo de la palabra de 16 bits elegida que se vuelca en R0 u otro registro.
  • La instrucción LPM se usa cuando se usan tablas.
  • La memoria de programa(ROM CODE) es parte de memoria Flash.
  • Cuando se apunta a una dirección de flash para leer el valor de dicha dirección se realiza pensando apuntando a su parte baja o alta de tal dirección.

fuente,fuente2

No hay comentarios:

Publicar un comentario

Uso del firmware original de la grabadora USBasp AVR en MX-USBASP (clon chino)

Te vendieron un USBisp pensado que es un USBasp?? Hace 2 meses compré un "USBasp" fui a probarlo y no funcionó....pensé me estafar...