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