1

I am trying to write some code for an ATmega16. I have been using the avra (version 1.4.2) under FreeBSD 12.2-RELEASE. I have the following in my code segment:

helloStr:   .db "Hello World\0"

It is my understanding that the bytes of the characters should be contiguous. However when I look at the object file produced I see the following (I am assembling the code using the command avra main.asm):

00000190: 0000 3600 0000 2a65 4800 0039 0000 002b  ..6...*eH..9...+                                                    
000001a0: 6c6c 0000 3900 0000 2c20 6f00 0039 0000  ll..9..., o..9..                                                    
000001b0: 002d 6f57 0000 3900 0000 2e6c 7200 0039  .-oW..9....lr..9                                                    
000001c0: 0000 002f 5c64 0000 3900 0000 3000 3000  .../\d..9...0.0.                                                    
000001d0: 0039 0000 0031 e2fa 0000 3d00 0000 32e0  .9...1....=...2.

Notice on the right that the characters aren't consecutive. I'm looking at the .obj file that avra is producing. When I try to run the code it seems to confirm my suspensions that the character bytes are not being stored contiguously as I get mostly garbage on the display with some of the correct characters, but spaced far too far apart. I don't think there is anything wrong with my display routine (The LCD display code will display a character correctly if I remove the looping code and store the character directly in r16 using ldi r16, 'H', for example.):

WRITE_TO_LCD:
    push    r16
    push    r17
START_WRITE_TO_LCD:

    lpm r16, Z+
    
    ldi r17, 0b0
    cp  r16, r17        ; Have we hit the null byte?
    breq    END_WRITE_TO_LCD
    ;; Output character command.
    out PortA, r16
    ldi r16, low(registerSelect)    ; Set RS control signal
    out PortC, r16
    ;; Set E and RS control siginals.
    ldi r16, (low(registerSelect) | low(enable))
    out PortC, r16
    ldi r16, low(registerSelect)    ; Clear E control signal
    out PortC, r16
    jmp START_WRITE_TO_LCD
END_WRITE_TO_LCD:
    pop r17
    pop r16
    ret

I'm loading Z with:

    ldi r31, low(helloStr)
    ldi r30, high(helloStr)

before I call WRITE_TO_LCD. I'm not sure if low to r31 and high to r30 is the right way around but I have also tried the other way. I also read that the memory is addressed using 2 byte words so I should use 2*helloStr. I've tried doing that too. Maybe these details that I have just mentioned aren't right in the code I've shown here but I've tried all the permutations and I don't think it's the problem (as evidenced by the out put on the LCD and what I can see in the hex editor.)

Also I have define helloStr after my interrupt vector. If I place it before the interrupt vector I can't seem to see any evidence of it in the .obj file and the output on the LCD is different when I actually run it. I assume that this has something to do with the interrupt vector needing to be the first thing in memory or something like that. But I would have though that it would have still shown up in the code and the handling of interrupts would be messed up.

Anyway the thing I'm really interested in is getting a contiguous string in flash so I can loop over it.

If anyone has any idea what I might be doing wrong I would very much appreciate your input.

SamNt
  • 11
  • 1
  • That seems to be a peculiarity of the object file format. I just put your string into a file on its own, and can see the same thing. However, avra says _"Code : 7 words (14 bytes)"_ which is correct and the `hex` file is also correct. How do you produce the final image? Have you looked inside that with a hex editor? – Jester Feb 23 '21 at 20:27
  • When I run the avra main.asm command it produces the following files: main.eep.hex, main.hex and main.obj. I write main.hex to the micro using avrdude. The reason I wasn't looking at the hex file is because it's an ascii representation of hex and harder to figure out what's going on in terms of the string. I guess now that I think about it it shouldn't take too long to verify it that way. There still must be something wrong with my code though :'( haha. Also thanks for your reply. – SamNt Feb 23 '21 at 20:32
  • Yes, you should use the `2*helloStr` and make sure you put the low byte into `r30` (your code is reversed). – Jester Feb 23 '21 at 20:36
  • Your right. I mean not that I didn't believe you. I just put it into this handy sight: https://www.binaryhexconverter.com/hex-to-ascii-text-converter I assume there must be something wrong with how I'm addressing the string then. I've spent quite a bit of time trying to get it to work though. So I'm not really sure what the problem could be. – SamNt Feb 23 '21 at 20:38
  • Okay thanks :). I'll try that out now – SamNt Feb 23 '21 at 20:38
  • 1
    That fixed it! Thanks a lot. I feel sort of stupid haha. I swear I had tried that. There are still a couple of things wrong with the code I posted though. It seems to need some nop's after enable is set high (I'm running the micro at 1MHz and the LCD is a 1602A) and also I don't think that the assembler is turning \0 into a null byte. Anyway it's working :). – SamNt Feb 23 '21 at 20:50

0 Answers0