Nie mam czasu na pełne wyjaśnienie, ale mogę dać ci polecenia w stylu książki kucharskiej, których używam na moim Linux-ie do programowania AVR:
Przygotowania
- Na Ubuntu upewnij się, że zainstalowano kilka wymaganych pakietów:
sudo apt-get install avr-libc avrdude binutils-avr gcc-avr srecord
opcjonalnie wrzuć gdb-avr simulavr
do debugowania i symulacji.
- Zacząłem tworzyć katalog, w którym wszystkie moje projekty ATtiny znajdują dom:
mkdir ~/attiny: cd ~/attiny
- Dla każdego projektu tworzę dedykowany podfolder (i nie przeszkadza mi długie nazwy):
mkdir waveShare4digit8segmentDisplay; cd waveShare4digit8segmentDisplay
Utwórz źródło
- Edytuj plik źródłowy za pomocą swojego ulubionego edytora tekstu:
vi project.cpp
Ustawienia
Poniższe polecenia w dużej mierze opierają się na zmiennych środowiskowych, aby ułatwić konserwację.
- Podstawowa nazwa użytych / utworzonych plików:
src=project
- Typowe flagi kompilatora:
cflags="-g -DF_CPU=${avrFreq} -Wall -Os - Werror -Wextra"
Poniższe zmienne mogą wymagać zmiany w zależności od używanego programatora. Szczegółowe informacje znajdują się na man
stronach.
baud=19200
Prędkość, z którą programista komunikuje się z komputerem:
programmerDev=/dev/ttyUSB003
Nazwa urządzenia, w którym znajduje się programator. Sprawdź dmesg
dane wyjściowe, aby uzyskać szczegółowe informacje.
programmerType=avrisp
To może być inne dla twojego dokładnego programisty.
Poniższe zmienne zależą od konkretnego kontrolera, który chcesz zaprogramować:
avrType=attiny2313
Sprawdź avrdude -c $programmerType
obsługiwane urządzenia.
avrFreq=1000000
Sprawdź arkusz danych kontrolera pod kątem domyślnego zegara.
Skompilować
- Pierwszym krokiem jest utworzenie pliku obiektowego:
avr-gcc ${cflags) -mmcu=${avrType) -Wa,-ahlmns=${src).lst -c -o ${src).o ${src).cpp
- Drugim krokiem jest utworzenie pliku ELF:
avr-gcc ${cflags) -mmcu=${avrType) -o ${src).elf ${src).o
- Trzecim krokiem jest utworzenie pliku Intel Hex, jest to plik, który jest faktycznie wysyłany do programisty:
avr-objcopy -j .text -j .data -O ihex ${src).elf ${src).flash.hex
Programowanie
- Ostatnim krokiem jest zaprogramowanie urządzenia:
avrdude -p${avrType} -c${programmerType} -P${programmerDev} -b${baud} -v -U flash:w:${src}.flash.hex
Makefile
Jako alternatywę dla zapamiętywania poleceń, przygotowałem makefile według własnych upodobań, możesz zapisać go pod nazwą Makefile
(pamiętaj o stolicy M
). Działa w następujący sposób:
make makefile
Edytuj plik makefile;
make edit
Edytuj plik źródłowy;
make flash
Zaprogramuj pamięć flash urządzenia;
make help
Lista innych poleceń.
Oto plik 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
Może wydawać się konieczne uruchomienie, avrdude
ponieważ root
jeśli tak się stanie, uzasadnia to samo pytanie . Można to rozwiązać za pomocą, udev
ale wymaga nieco konkretnych informacji od tego, jak programista jest rozpoznawany przez system operacyjny.
Witaj świecie
Pozwól mi wrzucić „Hello World”, który powoduje, że styk 2 kontrolera (PB3) (np. ATtiny13, ATtiny45, ATtiny85) przełącza się na 1 Hz. Podłącz diodę LED i rezystor szeregowy do styku, a dioda LED powinna zacząć migać.
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
Gotowy.