Programmation embarquée
Sommaire
résumé
le TP de la semaine de la fabacademy consiste à se familiariser avec la programmation de microcontroleurs et processeurs.
je vais commencer par programmer les deux circuits que j'ai réalisé : le FabISP et le helloWorld
premiers pas
La première étape est de finir mon travail en retard sur le fabISP : comme j'attendais l'arrivée des composants, je n'ai pas eu le temps de programmer le circuit à temps. De plus je ne comprenais pas bien la logique d'alimentation du circuit : je croyais que le programmateur alimentait la puce cible alors qu'il fallait qu'elle le soit séparément...
cette fois ça marche en suivant le protocole du tutoriel
make -f hello.ftdi.44.echo.c.make
avr-objcopy -O ihex hello.ftdi.44.echo.out hello.ftdi.44.echo.c.hex;\
avr-size --mcu=attiny44 --format=avr hello.ftdi.44.echo.out
AVR Memory Usage
Device: attiny44
Program: 776 bytes (18.9% Full) (.text + .data + .bootloader)
Data: 64 bytes (25.0% Full) (.data + .bss + .noinit)
cedric@cedric-Inspiron-5520 ~/fabacademy/electronicDesign/programming $ make -f hello.ftdi.44.echo.c.make program-avrisp2-fuses
avr-objcopy -O ihex hello.ftdi.44.echo.out hello.ftdi.44.echo.c.hex;\
avr-size --mcu=attiny44 --format=avr hello.ftdi.44.echo.out
AVR Memory Usage
Device: attiny44
Program: 776 bytes (18.9% Full) (.text + .data + .bootloader)
Data: 64 bytes (25.0% Full) (.data + .bss + .noinit)
avrdude -p t44 -P usb -c avrisp2 -U lfuse:w:0x5E:m
avrdude: AVR device initialized and ready to accept instructions
Reading | ################################################## | 100% 0.00s
avrdude: Device signature = 0x1e9207 avrdude: reading input file "0x5E" avrdude: writing lfuse (1 bytes):
Writing | ################################################## | 100% 0.01s
avrdude: 1 bytes of lfuse written avrdude: verifying lfuse memory against 0x5E: avrdude: load data lfuse data from input file 0x5E: avrdude: input file 0x5E contains 1 bytes avrdude: reading on-chip lfuse data:
Reading | ################################################## | 100% 0.00s
avrdude: verifying ... avrdude: 1 bytes of lfuse verified
avrdude: safemode: Fuses OK
avrdude done. Thank you.
$ make -f hello.ftdi.44.echo.c.make program-avrisp2 avr-objcopy -O ihex hello.ftdi.44.echo.out hello.ftdi.44.echo.c.hex;\ avr-size --mcu=attiny44 --format=avr hello.ftdi.44.echo.out AVR Memory Usage
Device: attiny44
Program: 776 bytes (18.9% Full) (.text + .data + .bootloader)
Data: 64 bytes (25.0% Full) (.data + .bss + .noinit)
avrdude -p t44 -P usb -c avrisp2 -U flash:w:hello.ftdi.44.echo.c.hex
avrdude: AVR device initialized and ready to accept instructions
Reading | ################################################## | 100% 0.00s
avrdude: Device signature = 0x1e9207 avrdude: NOTE: FLASH memory has been specified, an erase cycle will be performed
To disable this feature, specify the -D option.
avrdude: erasing chip avrdude: reading input file "hello.ftdi.44.echo.c.hex" avrdude: input file hello.ftdi.44.echo.c.hex auto detected as Intel Hex avrdude: writing flash (776 bytes):
Writing | ################################################## | 100% 0.27s
avrdude: 776 bytes of flash written avrdude: verifying flash memory against hello.ftdi.44.echo.c.hex: avrdude: load data flash data from input file hello.ftdi.44.echo.c.hex: avrdude: input file hello.ftdi.44.echo.c.hex auto detected as Intel Hex avrdude: input file hello.ftdi.44.echo.c.hex contains 776 bytes avrdude: reading on-chip flash data:
Reading | ################################################## | 100% 0.23s
avrdude: verifying ... avrdude: 776 bytes of flash verified
avrdude: safemode: Fuses OK
avrdude done. Thank you.
Par contre, le programme ne répond pas par le port série.
en explorant les différents codes, j'ai trouvé dans http://academy.cba.mit.edu/classes/embedded_programming/hello.ftdi.44.echo.interrupt.c
un commentaire de neil : "set lfuse to 0x7E for 20 MHz xtal"
or dans la makefile que j'ai utilisé, le fuse est seté à 0x5E
j'essaye de comprendre le datasheet pour résoudre ce probleme...
Dans le datasheet, il est question de la calibration de l'oscilateur: "...OSCCAL = 0x7F gives a higher frequency than OSCCAL = 0x80..."
je n'ai pas réussi à décoder exactement le code pour comprendre à quoi correspond ce setting
mais je vois qu'il est question de selectionner l'external clock et le multiple de l'horloge.
En tous cas, le circuit fonctionne : je peux commencer à essayer de la programmer
il suffit de modifier le makefile en remplaçant :
program-avrisp2-fuses: $(PROJECT).hex
avrdude -p t44 -P usb -c avrisp2 -U lfuse:w:0x5E:m
par
program-avrisp2-fuses: $(PROJECT).hex
avrdude -p t44 -P usb -c avrisp2 -U lfuse:w:0x7F:m
en assembleur
j'ai choisi la facilité : au lieu d'écrire en hexadécimal, je vais utiliser l'assembleur...
En partant de l'exemple de Neil, je vais essayer de faire un clignoter ma led.
je commence à lire le programme et je trouve :
ldi temp, (1 << CLKPCE)
ldi temp1, (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0)
en lisant le datasheet, je comprends que :
'ldi = load immediate
(p30)
CLKPCE=1 : Clock Prescaler Change Enable
(0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0) : Clock prescaler select : Clock division factor = 1
donc logiquement, le systeme doit fonctionner à la fréquence du quarts (qui est l'orloge externe : 20mhz)
compilation
il faut avoir téléchargé le compilateur gavrasm
j'arrive à compiler mon code, mais la led ne clignote pas...
quelques pistes sur l'assembleur
http://www.unixgarden.com/index.php/gnu-linux-magazine/coder-pour-atmel-attiny
des histoires d'horloge
voici ma boucle de délai :
delai:
;ldi temp, 255; max ;clr temp delay_loop: dec temp clr temp1 delay_loop2: dec temp1 clr temp2
delay_loop3:
dec temp2 brne delay_loop3 brne delay_loop2 brne delay_loop ret
malgré une boucle de délai conséquente (255^3), je ne voyais pas la led clignoter.
pourtant 255*255*255=16581375 cycles
et l'horloge tourne à 20Mhz, soit un cycle toutes les 1/20000000=0,00000005 sec
donc logiquement ma boucle devrai faire :
16581375*0,00000005=0,8s
or je ne vois pas le clignotement.
Par contre en changeant le diviseur de l'horloge à 256
ldi temp, (1 << CLKPCE)
ldi temp1, (1 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0);/256
out CLKPR, temp
out CLKPR, temp1
le clignotement est apparent et dure à peu près la durée prévue. J'ai donc fait des erreurs de calcul?