Pages

Saturday, 4 July 2020

Playing Arduino: Programming Arduino UNO with Assembly language without GUI on Linux

After successfully building a development env for programming Arduino with pure C, I will go to an even lower level in this post,  programming Arduino with assembly language on Linux.

1 Install packages

Only two packages are needed.
  • avr-binutils
# yum install avr-binutils
  • avrdude
# yum install avrdude

2 Source code LED.asm

$ cat led.asm
;===============================================================
; file: led.asm
; desc: This is a simple demo code to blink Arduino Uno R3's
;       builtin LED connected to Pin 13 ( the 5th bit of PortB )
;===============================================================

; directive to tell avr-as to put next instruction at 0x0000 on ROM space
.ORG 0x0000

; directives to define const
.equ SPL, 0x3d
.equ SPH, 0x3e
.equ DDRB, 0x04
.equ PORTB, 0x05

; initialize stack by configuring SPH,SPL
; to the last data ram location 0x08FF
; The stack must be setup before any CALL instructions
ldi r16, 0x08
out SPH, r16
ldi r16, 0xFF
out SPL, r16

; Configure Port B to work in output mode
ldi r16, 0xFF
out DDRB, r16

; Turn on/off LED indefinately
LOOP:
  sbi PORTB, 5       ; switch on the LED
  rcall QDELAY       ; wait for one fourth second
  cbi PORTB, 5       ; switch it off
  rcall QDELAY       ; wait for one fourth second
  rjmp LOOP

; The is a function for delaying 250 ms
QDELAY:
        LDI R20, 16
D0:
        LDI R21, 200
D1:
        LDI R22, 250
D2:
        NOP
        DEC R22
        BRNE D2
        DEC R21
        BRNE D1
        DEC R20
        BRNE D0
        RET

3 Makefile


$ cat Makefile
all: led.hex

led.hex: led.elf
        # generate Intel Hex format file
        avr-objcopy -O ihex $< $@

led.elf: led.o
        # link object file to executable file
        avr-ld -o $@ $<

led.o: led.asm
        # assembly source code to elf object file
        avr-as -mmcu atmega328p -o $@ $<

clean:
        rm -f *.o *.elf *.hex

deploy: led.hex
        avrdude -F -V -c arduino -p ATMEGA328p \
                -P /dev/ttyACM0 \
                -b 115200 \
                -U flash:w:$^

4 Run it

$ make deploy

Then you'll see the built-in LED on your Arduino UNO R3 board blinking happily forever!

5 Some notes

  • .equ has different syntax in AVR Studio on Windows and avr-as on Linux.
    • AVR Studio: .equ SPH = 0x3e
    • avr-as: .equ SPH, 0x3e
  • Both avr-as and avr-ld have the same default output file name, a.out. This will cause a problem if you don't use a specific output file name.
         $ avr-as -mmcu atmega328p led.asm
         $ avr-ld a.out
         a.out: file not recognized: File truncated

         This is because the avr-ld now uses a.out as both input and output file name!

  • avr-objcopy works on object file too, but it's not what we want.

         $ file led.o
         led.o: ELF 32-bit LSB relocatable, Atmel AVR 8-bit, version 1 (SYSV), not stripped

         $ avr-objcopy -O ihex led.o led.hex

         However, this is NOT what you want! led.o has unresolved addresses (marked as all 0). The led.hex generated has instructions with addresses operand as 0 instead! 


No comments:

Post a Comment