MCU: ATmega1284
Programador: JTAGICE3
IDE: Atmel Studio 7.0.2397
Idioma: Ensamblador AVR
Tengo una tabla de datos constante en la memoria flash. El enlazador cree que está ubicado en la dirección 0x0090, por lo que cuando escribo las instrucciones de ensamblaje para intentar cargar la dirección de la tabla, cargan 0x0090. El problema es que la tabla en realidad se encuentra en la dirección 0x0120. Entonces, cuando intento acceder a la tabla, obtengo basura.
¿Por qué el enlazador piensa que la tabla de datos está ubicada en una dirección diferente de donde realmente se está programando?
Aquí está la definición de la tabla.
.cseg
.align 16
lcd_init_table: .db \
0xEF , 0x03, 0x03, 0x80, 0x02, \
0xCF , 0x03, 0x00, 0xC1, 0x30, \
0xED , 0x04, 0x64, 0x03, 0x12, 0x81, \
0xE8 , 0x03, 0x85, 0x00, 0x78, \
0xCB , 0x05, 0x39, 0x2C, 0x00, 0x34, 0x02, \
0xF7 , 0x01, 0x20, \
0xEA , 0x02, 0x00, 0x00, \
0xC0 , 0x01, 0x23, \
0xC1 , 0x01, 0x10, \
0xC5 , 0x02, 0x3e, 0x28, \
0xC7 , 0x01, 0x86, \
0x36 , 0x01, 0x48, \
0x37 , 0x01, 0x00, \
0x3A , 0x01, 0x55, \
0xB1 , 0x02, 0x00, 0x18, \
0xB6 , 0x03, 0x08, 0x82, 0x27, \
0xF2 , 0x01, 0x00, \
0x26 , 0x01, 0x01, \
0xE0 , 0x0F, 0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, 0x4E , 0xF1, 0x37, 0x07, 0x10, 0x03, 0x0E, 0x09, 0x00, \
0xE1 , 0x0F, 0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, 0x31 , 0xC1, 0x48, 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F, \
0x11 , 0x80, \
0x29 , 0x80, \
0x00 , 0x00
Quiero acceder a la tabla usando la instrucción AVR ELPM de la siguiente manera...
;Load Z register with table address
ldi zh, lcd_init_table >> 8
ldi zl, lcd_init_table & 0xFF
clr r16
out RAMPZ, r16
lcd_init_loop:
elpm r16, Z+ ;load command
tst r16
breq lcd_init_done
call lcd_write_cmd ;write command to LCD
elpm r16, Z+ ;load wait and num args
mov r17, r16
andi r16, 0x7F ;extract num_args
breq lcd_init_skip_args
call lcd_write_bytes_from_mcu_rom ;write rom bytes to LCD
lcd_init_skip_args:
andi r17, 0x80 ;extract wait flag
breq lcd_init_loop ;if wait flag is set...
ldi r16, 150 ;wait 150 ms
call wait_ms
jmp lcd_init_loop ;go back to init loop
lcd_init_done:
El problema es que cuando trato de cargar el registro Z con la dirección de lcd_init_table obtengo el valor 0x0090. El archivo de mapa confirma que 0x0090 es donde el enlazador cree que se encuentra la tabla.
CSEG lcd_init_table 00000090
El problema es que la mesa no está realmente ubicada allí. El archivo hexadecimal muestra que en realidad se encuentra en 0x0120. Programar la MCU y mirar el flash usando la ventana de memoria confirma que la tabla realmente está en 0x0120.
Si codifico la carga de la dirección en función de la ubicación en el archivo hexadecimal, entonces el código funciona según lo previsto. El problema es que realmente no puedo hacer eso, ya que la tabla podría moverse a medida que agrego o elimino código. Podría ubicar la tabla en una dirección explícita usando una directiva .org, pero eso es solo una curita y me gustaría resolver el problema real.
;Load Z register with table address
ldi zh, 0x01
ldi zl, 0x20
La configuración del programador del dispositivo es la siguiente.
0120h es 0090h multiplicado por 2.
En AVR, Z es un registro, por lo que tiene una dirección de bytes (entonces, lo que se direcciona a través de Z), mientras que la tabla en la memoria tiene una dirección de palabra (16 bits). Así que multiplicar Z por 2 resolverá el problema.
usuario4574