Assembleur AVR avec GNU AS

Récemment, j’ai dû modifier plusieurs codes sources en assembleur que j’avais écrit pour tavrasm. Manque de bol, tavrasm n’est plus maintenu et les sources sont introuvables 🙁[1]

J’ai regardé du coté de avra, la syntaxe est proche mais il n’y a pas eu de nouvelle version depuis 2007: là aussi, ça sent le sapin.

Correctif: Une nouvelle version de AVRA est sortie 6 mois après la date de cet article.

Du coup, je me suis tourné vers une valeur sûre, à savoir GNU as (gas pour les intimes) dans sa version AVR. Plutôt qu’un long discours, voici un petit exemple de « portage » commenté:

La version TAVRASM

; --
; Hello world (aka "la laide qui clignote")

.def temp     =  r16
.def counter1 =  r17
.def counter2 =  r18
.def counter3 =  r19

.include "2313def.inc"

        rjmp initSTACK 

; --
; Stack Initialization

initSTACK:
        ldi temp,RAMEND
        out spl,temp
        rjmp main

; --
; Delays loops

timer200ms:
        ldi counter1,0x65
t200ms: dec counter1
        breq t0
        ldi counter2,0x65
t2ms:   dec counter2
        breq t200ms
        ldi counter3,0x14
t20us:  dec counter3
        breq t2ms
        rjmp t20us
t0:     ret

; --
; Main 

main:
	ldi temp,0x01 		; Pin 1 du port B en sortie
	out ddrb,temp
loop:
	ldi temp,0x01
	out portb,temp          ; on
	rcall timer200ms
	ldi temp,0x00
	out portb,temp          ; off
	rcall timer200ms
	rjmp loop

La même en version pour GNU AVR-AS:

; --
; Plus besoin d'inclure 2313def.inc, avr-gcc charge l'include
; du MCU correspondant avec l'option -mmu à la compilation.
#include <avr/io.h>
#define temp 	        r16
#define counter1 	r17
#define counter2 	r18
#define counter3 	r19

.global main

; No need for Stack Initialization

       rjmp main
; --
; Timers
timer200ms:
        ldi counter1,0x65
t200ms:
        dec counter1
        breq t0
        ldi counter2,0x65
t2ms:
        dec counter2
        breq t200ms
        ldi counter3,0x14
t20us:
        dec counter3
        breq t2ms
        rjmp t20us
t0:
        ret

; --
; Main loop
main:
	ldi temp,0x01 		; Pin 1 du port B en sortie
	out _SFR_IO_ADDR(DDRB),temp
loop:
	ldi temp,0x01
        out _SFR_IO_ADDR(PORTB),temp    ; on
	rcall timer200ms
	ldi temp,0x00
        out _SFR_IO_ADDR(PORTB),temp    ; off
        rcall timer200ms
	rjmp loop

La petite subtilité est que avr-as n’inclut pas les fichiers d’entêtes ".h". Il faut utiliser le préprocesseur de avr-gcc avec l’option -x assembler-with-cpp:

 avr-gcc -Os -mmcu=at90s2313 -x assembler-with-cpp
-gstabs -I /usr/local/avr/include -c foo.s -o foo.o

Pour faciliter la tâche, voici un Makefile[2] qui fait tout le boulot:

# Copyright (c) 2006-2010 Luc HONDAREYTE
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or
# without modification, are permitted provided that the
# following conditions are met:
# Redistributions of source code must retain the above
# copyright notice.
# $Id$
#

FIRMWARE	:=sample
MCU		:=attiny2313

#
# Vous ne devriez pas avoir besoin de modifier ce qui suit
CC		:= avr-gcc
OBJCOPY		:= avr-objcopy
OBJDUMP		:= avr-objdump
ASMFLAGS	:=-Os -mmcu=$(MCU) -x assembler-with-cpp -gstabs \
                     -I /usr/local/avr/include
CFLAGS		:=-Os -mmcu=$(MCU) -I /usr/local/avr/include
SOURCES         := $(wildcard *.s)
OBJECTS         := $(patsubst %.s,%.o,$(SOURCES))

all: $(FIRMWARE).hex

$(FIRMWARE).hex: $(FIRMWARE).out
	@printf "Generating $(FIRMWARE).hex..."
	@$(OBJCOPY) -R .eeprom -O ihex $(FIRMWARE).out \
		$(FIRMWARE).hex
	@echo "done."

$(FIRMWARE).out: $(OBJECTS)
	@printf "Linking    $(FIRMWARE)..."
	@$(CC) $(CFLAGS) -o $(FIRMWARE).out \
		-Wl,-Map,$(FIRMWARE).map $(OBJECTS)
	@echo "done."

.s.o:
	@printf "Compiling  $<..."
	@$(CC) $(ASMFLAGS) -c $< -o $@
	@echo "done."

bin: $(FIRMWARE).hex
	@printf "Generating binary file..."
	@$(OBJCOPY) -R .eeprom -O binary $(FIRMWARE).out \
		$(FIRMWARE).bin
	@echo "done."
	@ls -l $(FIRMWARE).bin

#EOF

Liens:

Notes

[1] Ça m’apprendra a faire confiance aux logiciels « Open source » …
[2] Compatible gmake uniquement.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

*

Vous pouvez utiliser ces balises et attributs HTML : <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>