Non ho tempo per una spiegazione completa, ma posso darti in stile ricettario i comandi che uso sulla mia scatola di Linux per programmare gli AVR:
preparativi
- Su Ubuntu, assicurati che siano installati diversi pacchetti richiesti:
sudo apt-get install avr-libc avrdude binutils-avr gcc-avr srecord
facoltativamente, lancia il gdb-avr simulavr
debug e la simulazione.
- Ho iniziato a creare una directory in cui tutti i miei progetti ATtiny trovano casa:
mkdir ~/attiny: cd ~/attiny
- Per ogni progetto creo una sottocartella dedicata (e non mi dispiace i nomi lunghi):
mkdir waveShare4digit8segmentDisplay; cd waveShare4digit8segmentDisplay
Crea fonte
- Modifica il file sorgente con il tuo editor di testo preferito:
vi project.cpp
impostazioni
I comandi sottostanti si basano fortemente su variabili di ambiente, per facilitare la manutenzione.
- Il nome di base dei file utilizzati / creati:
src=project
- Flag comuni del compilatore:
cflags="-g -DF_CPU=${avrFreq} -Wall -Os - Werror -Wextra"
Potrebbe essere necessario modificare le variabili seguenti in base al programmatore esatto che si utilizza. Fare riferimento alle man
pagine per i dettagli.
baud=19200
Il baudrate al quale il tuo programmatore comunica con il PC:
programmerDev=/dev/ttyUSB003
Il nome del dispositivo in cui si trova il programmatore. Controlla l' dmesg
output per i dettagli.
programmerType=avrisp
Questo potrebbe essere diverso per il tuo programmatore esatto.
Le variabili seguenti dipendono dal controller esatto che si desidera programmare:
avrType=attiny2313
Controlla i avrdude -c $programmerType
dispositivi supportati.
avrFreq=1000000
Controllare il foglio dati del controller per l'orologio predefinito.
Compilare
- Il primo passo è creare un file oggetto:
avr-gcc ${cflags) -mmcu=${avrType) -Wa,-ahlmns=${src).lst -c -o ${src).o ${src).cpp
- Il secondo passo è creare un file ELF:
avr-gcc ${cflags) -mmcu=${avrType) -o ${src).elf ${src).o
- Il terzo passo è creare un file Intel Hex, questo è il file che viene effettivamente inviato al programmatore:
avr-objcopy -j .text -j .data -O ihex ${src).elf ${src).flash.hex
Programmazione
- L'ultimo passo è programmare il dispositivo:
avrdude -p${avrType} -c${programmerType} -P${programmerDev} -b${baud} -v -U flash:w:${src}.flash.hex
Makefile
In alternativa al ricordare i comandi, ho preparato un makefile per i miei gusti personali, puoi salvarlo con il nome Makefile
(mente la capitale M
). Funziona come segue:
make makefile
Modifica il makefile;
make edit
Modifica il file sorgente;
make flash
Programmare la memoria flash del dispositivo;
make help
Elenca altri comandi.
Ecco il makefile:
baud=19200
src=project
avrType=attiny2313
avrFreq=4000000 # 4MHz for accurate baudrate timing
programmerDev=/dev/ttyUSB003
programmerType=arduino
cflags=-g -DF_CPU=$(avrFreq) -Wall -Os -Werror -Wextra
memoryTypes=calibration eeprom efuse flash fuse hfuse lfuse lock signature application apptable boot prodsig usersig
.PHONY: backup clean disassemble dumpelf edit eeprom elf flash fuses help hex makefile object program
help:
@echo 'backup Read all known memory types from controller and write it into a file. Available memory types: $(memoryTypes)'
@echo 'clean Delete automatically created files.'
@echo 'disassemble Compile source code, then disassemble object file to mnemonics.'
@echo 'dumpelf Dump the contents of the .elf file. Useful for information purposes only.'
@echo 'edit Edit the .cpp source file.'
@echo 'eeprom Extract EEPROM data from .elf file and program the device with it.'
@echo 'elf Create $(src).elf'
@echo 'flash Program $(src).hex to controller flash memory.'
@echo 'fuses Extract FUSES data from .elf file and program the device with it.'
@echo 'help Show this text.'
@echo 'hex Create all hex files for flash, eeprom and fuses.'
@echo 'object Create $(src).o'
@echo 'program Do all programming to controller.'
edit:
vi $(src).cpp
makefile:
vi Makefile
#all: object elf hex
clean:
rm $(src).elf $(src).eeprom.hex $(src).fuses.hex $(src).lfuse.hex $(src).hfuse.hex $(src).efuse.hex $(src).flash.hex $(src).o
date
object:
avr-gcc $(cflags) -mmcu=$(avrType) -Wa,-ahlmns=$(src).lst -c -o $(src).o $(src).cpp
elf: object
avr-gcc $(cflags) -mmcu=$(avrType) -o $(src).elf $(src).o
chmod a-x $(src).elf 2>&1
hex: elf
avr-objcopy -j .text -j .data -O ihex $(src).elf $(src).flash.hex
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 -O ihex $(src).elf $(src).eeprom.hex
avr-objcopy -j .fuse -O ihex $(src).elf $(src).fuses.hex --change-section-lma .fuse=0
srec_cat $(src).fuses.hex -Intel -crop 0x00 0x01 -offset 0x00 -O $(src).lfuse.hex -Intel
srec_cat $(src).fuses.hex -Intel -crop 0x01 0x02 -offset -0x01 -O $(src).hfuse.hex -Intel
srec_cat $(src).fuses.hex -Intel -crop 0x02 0x03 -offset -0x02 -O $(src).efuse.hex -Intel
disassemble: elf
avr-objdump -s -j .fuse $(src).elf
avr-objdump -C -d $(src).elf 2>&1
eeprom: hex
#avrdude -p$(avrType) -c$(programmerType) -P$(programmerDev) -b$(baud) -v -U eeprom:w:$(src).eeprom.hex
date
fuses: hex
avrdude -p$(avrType) -c$(programmerType) -P$(programmerDev) -b$(baud) -v -U lfuse:w:$(src).lfuse.hex
#avrdude -p$(avrType) -c$(programmerType) -P$(programmerDev) -b$(baud) -v -U hfuse:w:$(src).hfuse.hex
#avrdude -p$(avrType) -c$(programmerType) -P$(programmerDev) -b$(baud) -v -U efuse:w:$(src).efuse.hex
date
dumpelf: elf
avr-objdump -s -h $(src).elf
program: flash eeprom fuses
flash: hex
avrdude -p$(avrType) -c$(programmerType) -P$(programmerDev) -b$(baud) -v -U flash:w:$(src).flash.hex
date
backup:
@for memory in $(memoryTypes); do \
avrdude -p $(avrType) -c$(programmerType) -P$(programmerDev) -b$(baud) -v -U $$memory:r:./$(avrType).$$memory.hex:i; \
done
Può sembrare necessario eseguire avrdude
come root
, se ciò accade, giustifica una domanda a sé stante . Può essere risolto udev
ma richiede alcune informazioni specifiche su come il programmatore viene riconosciuto dal sistema operativo.
Ciao mondo
Permettetemi di lanciare un 'Hello World' che fa in modo che un pin del controller 2 (PB3) (es. ATtiny13, ATtiny45, ATtiny85) si attivi a 1Hz. Collegare un LED e un resistore serie al pin e il LED dovrebbe iniziare a lampeggiare.
i
#include <avr/io.h>
#include <util/delay.h>
int main(void)
{
DDRB = 0x08;
while (1) {
PORTB = 0x00; _delay_ms(500);
PORTB = 0x08; _delay_ms(500);
}
}
<ESC>:wq
Fatto.