PlatformIO Community

Atmelavr assembler (directives and some commands)

Hello all,
I usually assemble my programs with avra under linux.
Now I am trying to assemble a program that I wrote for an atmega328 with PlatformIO in VSC instead.
Some assembler directives do not work, for example the .equ I found I have to use #define (c precompiler)
Also the HIGH() and LOW() commands do not work and I have no idea what to use instead.

Is there a manual for the assembler used by the PlatformIO toolchain?
It does not look like the avr-asm of the avr toolchain.

Thank you very much for the answer

.S files are assembled by PlatformIO with avr-gcc -x assembler-with-cpp, as can be observed when executing the project task Advanced → Verbose Build. So it’s a combination of the C pre-processor with avr-as (AVR GNU assembler). See avr-libc: avr-libc and assembler programs and Top (Using as).

Thank you maxgerhardt,
this is exactly the problem:

  • the “Using as” document gives the .equ directive, but it does not work on PlatformIO
  • the avr-libc document gives hi8() and lo8() (these were the high and low I was looking for) but they don’t seem work on PlatformIO
    I try to compile this:
    	#define	SPL	            0x3d		;stack pointer low
    	#define	SPH	    0x3e		;stack pointer high
    	#define	RAMEND    0x08ff
    MAIN:	
    	LDI	R16,hi8(RAMEND)           ;line 152
    	OUT	SPH,R16
    	LDI	R16,lo8(RAMEND)
    	OUT	SPL,R16		;stack pointer

But I get this error:

Processing ATmega328 (platform: atmelavr; board: ATmega328)
-------------------------------------------------------------------------------------
Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/atmelavr/ATmega328.html
PLATFORM: Atmel AVR (3.4.0) > ATmega328
HARDWARE: ATMEGA328 16MHz, 2KB RAM, 32KB Flash
DEBUG: Current (avr-stub) On-board (avr-stub, simavr)
PACKAGES: 
 - toolchain-atmelavr 1.70300.191015 (7.3.0)
LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 0 compatible libraries
Scanning dependencies...
No dependencies
Building in release mode
Compiling .pio/build/ATmega328/src/main.o
src/main.S: Assembler messages:
src/main.S:152: Error: `)' required
src/main.S:153: Error: `,' required
src/main.S:153: Error: constant value required
src/main.S:153: Error: garbage at end of line
src/main.S:154: Error: `)' required
src/main.S:155: Error: `,' required
src/main.S:155: Error: constant value required
src/main.S:155: Error: garbage at end of line
src/main.S:187: Error: garbage at end of line
src/main.S:189: Error: garbage at end of line
src/main.S:230: Error: garbage at end of line
src/main.S:232: Error: garbage at end of line
*** [.pio/build/ATmega328/src/main.o] Error 1
============================ [FAILED] Took 0.74 seconds ============================
The terminal process "platformio 'run'" terminated with exit code: 1.

Is there an error in my code?

When I use // as the comment sign instead of ; (remember -x assembler-with-cpp) and define main as global symbol, with the file src\main.S,

.global main
    	#define	SPL	            0x3d		//stack pointer low
    	#define	SPH	    0x3e		//stack pointer high
    	#define	RAMEND    0x08ff
    main:	
    	LDI	R16,hi8(RAMEND)           //line 152
    	OUT	SPH,R16
    	LDI	R16,lo8(RAMEND)
    	OUT	SPL,R16		//stack pointer

with the platformio.ini

[env:ATmega328]
platform = atmelavr
board = ATmega328

I get

RAM:   [          ]   0.0% (used 0 bytes from 2048 bytes)
Flash: [          ]   0.4% (used 140 bytes from 32768 bytes)
=======[SUCCESS] Took 1.43 seconds ======

That when I avr-objdump the firmware.elf again gives me

00000080 <main>:
  80:   08 e0           ldi     r16, 0x08       ; 8
  82:   0e bf           out     0x3e, r16       ; 62
  84:   0f ef           ldi     r16, 0xFF       ; 255
  86:   0d bf           out     0x3d, r16       ; 61

so that looks like it makes perfect sense.

When I write in the above setup

.global main
    	.equ SPL, 0x3d		//stack pointer low
    	.equ SPH, 0x3e		//stack pointer high
    	.equ RAMEND, 0x08ff
    main:	
    	LDI	R16,hi8(RAMEND)           //line 152
    	OUT	SPH,R16
    	LDI	R16,lo8(RAMEND)
    	OUT	SPL,R16		//stack pointer

It assembles and disassembles to the exact same thing as in the post above.

RAM:   [          ]   0.0% (used 0 bytes from 2048 bytes)
Flash: [          ]   0.4% (used 140 bytes from 32768 bytes)
============= [SUCCESS] Took 1.50 seconds =============
>avr-objdump.exe -d .pio\build\ATmega328\firmware.elf
[...]
00000080 <main>:
  80:   08 e0           ldi     r16, 0x08       ; 8
  82:   0e bf           out     0x3e, r16       ; 62
  84:   0f ef           ldi     r16, 0xFF       ; 255
  86:   0d bf           out     0x3d, r16       ; 61

so, no problems there…

1 Like

I found my error for .equ, I wrote
.equ SPL = 0x3d, like for avra, instead of .equ SPL,0x3d

Since I changed the #define with .equ I don’t get the error for LDI R16,hi8(RAMEND) anymore.
Now I get an error :

Building in release mode
Linking .pio/build/ATmega328/firmware.elf
/home/reto/.platformio/packages/toolchain-atmelavr/bin/…/lib/gcc/avr/7.3.0/…/…/…/…/avr/lib/avr5/crtatmega328.o:(.init9+0x0): undefined reference to `main’
collect2: error: ld returned 1 exit status
*** [.pio/build/ATmega328/firmware.elf] Error 1

I’m looking at it

Done, it looks like it will a lowercase main (I used MAIN).
Also the lo8 and hi8 have to be lowercase (they are probably defined for gcc, so case sensitive)
For the comments I can let ; and it works

Thank you very much for your time !!!

Hellow. I have more question on avr-gcc. How to replace “>>” in example of uart.
log build

Error: invalid operands (*ABS* and *UND* sections) for `<<'

in source - part UART INIT

uart_init: LDI R16, lo8(bauddivider)
OUT UBRRL,R16
LDI R16, hi8(bauddivider)
OUT UBRRH,R16
LDI R16,0
OUT UCSRA, R16
LDI R16, (1<<RXEN)|(1<<TXEN)|(0<<RXCIE)|(0<<TXCIE)|(0<<UDRIE)
OUT UCSRB, R16
LDI R16, (1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1)
OUT UCSRC, R16

What’s your platformio.ini? Based on the register names you are working with an ATmega8 (since those registers / bit names don’t e.g. exist on a atmega328). When I take your code, add the missing defines you didn’t show and correct the OUT instruction to an STS instruction since the I/O address is beyond 0x3F, it assembles normally.

[env:ATmega8]
platform = atmelavr
board = ATmega8
.global main

#include <avr/io.h>
.equ 	XTAL, 8000000
.equ 	baudrate, 31250
.equ 	bauddivider, XTAL/(16*baudrate)-1

main:
    LDI R16, lo8(bauddivider)
    OUT UBRRL,R16
    LDI R16, hi8(bauddivider)
    sts UBRRH,R16
    LDI R16,0
    OUT UCSRA, R16
    LDI R16, (1<<RXEN)|(1<<TXEN)|(0<<RXCIE)|(0<<TXCIE)|(0<<UDRIE)
    OUT UCSRB, R16
    LDI R16, (1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1)
    sts UCSRC, R16    

Building in release mode
avr-gcc -mmcu=atmega8 -x assembler-with-cpp -DF_CPU=16000000L -DPLATFORMIO=60105 -DARDUINO_AVR_ATmega8 -Iinclude -Isrc -c -o .pio\build\ATmega8\src\main.o src\main.S
avr-gcc -o .pio\build\ATmega8\firmware.elf -mmcu=atmega8 -Os -Wl,–gc-sections -flto -fuse-linker-plugin .pio\build\ATmega8\src\main.o -L.pio\build\ATmega8 -Wl,–start-group -lm -Wl,–end-group
MethodWrapper([“checkprogsize”], [".pio\build\ATmega8\firmware.elf"])
Advanced Memory Usage is available via “PlatformIO Home > Project Inspect”
RAM: [ ] 0.0% (used 0 bytes from 1024 bytes)
Flash: [ ] 1.0% (used 84 bytes from 8192 bytes)

1 Like