3 - Compiler un premier programme

Une fois que votre programme vous semble juste, il faut le compiler. Cependant, il va falloir le compiler pour l'AVR, en effet le code ne sera pas executé par l'ordinateur mais bien par le processeur de la carte (ici un AVR). Vous compilez donc sur l'ordinateur mais pour un autre processeur. Il faut pour cela utiliser un autre gcc: avr-gcc.

Vérifiez tout d'abord que vous avez avr-gcc d'installé en tapant avr-gcc dans un terminal, s'il vous dit "command not found" vérifiez qu'il est correctement installer et que le binaire est bien dans votre PATH.

Si vous êtes sur Debian, il suffit d'installer les paquets :

  • avrdude
  • avrdude-doc
  • gcc-avr
  • avr-libc
  • binutils-avr

Ce compilateur nécessite des options de compilation:

  • Le type d'AVR utilisé pour savoir quels sont les fichiers qu'il doit inclure. En effet, certaines fonctions sont implémentées différemment selon le type d'AVR. Notre AVR est un ATMega88, on met donc -mmcu=atmega88 sur la ligne de compilation.
  • La fréquence de fonctionnement du processeur : -DF_CPU=20000000 En gros, l'option -D définit une variable. C'est donc la variable F_CPU que l'on fixe à 20MHz puisqu'on a mis un quartz de 20MHz
  • Les librairies nécessaires pour compiler sont surement placées dans un répertoire comme /usr/local/avr/avr/lib ou /usr/lib/avr/lib sauf si vous avez installé les librairies vous-même. Retrouvez ce répertoire sur votre ordinateur et mettre l'option -L /usr/avr/avr/lib. A l'école c'est ce répertoire qui est utilisé.
  • on peut demander à ce que toutes les warnings soient considérer comme des erreurs pour nous obliger à faire un code propre -Werror
  • on optimise la taille du code généré avec -Os
  • on limite la taille que peuvent prendre les fonctions inline avec -finline-limit=800

Vous pouvez donc compiler votre programme avec la ligne suivante:

avr-gcc -Os -finline-limit=800 -mmcu=atmega88 -DF_CPU=20000000 -Werror -L /usr/local/avr/avr/lib nom_du_programme.c -o nom_du_programme

Vous avez donc un programme executable pour un ATMega88 mais malheureusement, vous ne pouvez pas le tester sur votre ordinateur. Il faudra encore patienter jusqu'à ce qu'on ait mis le programme sur l'ATMega.

Pour mettre un programme sur l'ATMega il faut d'abord le transformer en .hex pour qu'il puisse être transférer par le port série. On utilise la commande avr-objcopy qui permet de convertir des fichiers objets en d'autres formats, l'option -O ihex dit que le fichier de sortie doit être en hexadecimal et l'option -R .eeprom dit qu'on enleve la section qui concerne l'eeprom. Cette option est utile car très souvent on stocke des données utiles à l'utilisateur dans l'eeprom (par exemple des infos de calibrage pour les webcams) et on ne veut pas que le programme qu'on va transférer les écrase. Ce qui nous donne la ligne de commande suivante:

avr-objcopy -O ihex -R .eeprom nom_du_programme nom_du_programme.hex

Gardez bien le fichier .hex car c'est lui qu'on va envoyer sur notre robot à la prochaine page. Mais avant cela voyons d'abord comment faire un Makefile au cas où nos projets deviennent plus gros.

Il existe de nombreux tutoriaux sur les Makefile c'est pourquoi je serai bref, nous verrons juste les points importants, pour comprendre la base, lisez cette page assez bien faite et succinte: http://mrbook.org/tutorials/make/ et pour plus d'infos la documentation officielle http://www.gnu.org/software/make/manual/make.html

Voici un exemple de Makefile ci dessous, regardez les commentaires en dessous.

# Notre AVR : ATMEGA88 à 20MHz
MCU = atmega88
F_CPU = 20000000
 
# Programme a construire
TARGET = test
 
# Ne plus toucher ci-dessous 
CC           = avr-gcc 
OBJCOPY      = avr-objcopy 
SIZE         = avr-size 
OBJECTS = $( patsubst %.c,%.o,$(shell echo *.c) ) 
HEADERS = $( shell echo *.h ) 
CFLAGS = -g -Os -finline-limit=800 -mmcu=$(MCU) -DF_CPU=$(F_CPU) -Werror 
LDFLAGS = -L /usr/local/avr/avr/lib -mmcu=$(MCU)  
 
all: $(TARGET).hex
	@echo "==============================="
	@echo "compiled for: $(MCU)"
	@echo -n "program size is: "
	@$(SIZE) -A $< | grep "\.sec1" | tr -s " " | cut -d" " -f2
	@echo "==============================="  
 
$(TARGET): $(OBJECTS) $(TARGET).o  
 
%.o: $(HEADERS)  
 
%.hex: %
	$(OBJCOPY) -O ihex -R .eeprom $< $@  
 
clean:
	rm -f $(TARGET).hex
	rm -f *~
	rm -f *.o
	rm -f $(TARGET)

ATTENTION, il se peut que votre navigateur remplace les tabulations du Makefile par un simple espace. Dans ce cas, remplacez tous les espaces en début de ligne par des tabulations.

 

Voilà, ce Makefile considère que tous les fichiers .c sont des fichiers sources du programme et va donc compiler tous les .c du dossier puis va faire le linkage. Ensuite il créera le fichier .hex avec la commande avr-objcopy. Ce qui est très pratique si on a un programme avec de nombreux fichiers sources. En plus, on pourra utiliser le même Makefile pour différents projets très simplement, puisqu'il suffit de changer le nom du TARGET et non pas le nom de tous les fichiers sources.

Vous pouvez le tester en le copiant dans un fichier appelé "Makefile" dans votre dossier de travail. Tapez ensuite la commande make. Vous devriez voir tous les fichiers se compiler puis le programme être linker et enfin la commande pour faire le .hex. Si ça ne marche pas, essayez d'abord de trouver par vous-même ce qui ne fonctionne pas et ensuite n'hésitez pas à poster sur la liste de diffusion pour les membres du clubs.

Quand tout fonctionne, on peut passer sereinement au transfert de ce premier programme sur le robot.