Makefile dasar untuk avr-gcc

7

Saya ingin membuat makefile untuk mengkompilasi program c untuk Arduino. Saya agak terbiasa dengan make tetapi belum pernah menggunakannya dengan avr-gcc. Apa cara paling sederhana saya bisa meletakkan perintah di bawah ini di makefile?

$ avr-gcc -Os -DF_CPU=16000000UL -mmcu=atmega328p -c -o led.o led.c
$ avr-gcc -mmcu=atmega328p led.o -o led
$ avr-objcopy -O ihex -R .eeprom led led.hex
$ avrdude -F -V -c arduino -p ATMEGA328P -P /dev/ttyACM0 -b 115200 -U flash:w:led.hex
Connorwstein
sumber
Karena ini adalah forum Arduino, akan lebih tepat untuk dikompilasi -I/usr/share/arduino/hardware/arduino/cores/arduino -I/usr/share/arduino/hardware/arduino/variants/standarddan dihubungkan secara politis libcore.a. :-)
Edgar Bonet

Jawaban:

5

Tidak ada bedanya dengan bekerja dengan Make dan segala bentuk GCC lainnya. Cukup atur variabel CC dan variabel CFLAGS Anda sesuai dan berfungsi seperti biasa.

Misalnya, saya baru saja mengetuk yang ini:

CC=avr-gcc
OBJCOPY=avr-objcopy

CFLAGS=-Os -DF_CPU=16000000UL -mmcu=atmega328p
PORT=/dev/ttyACM0

led.hex: led.elf
    ${OBJCOPY} -O ihex -R .eeprom led.elf led.hex

led.elf: led.o
    ${CC} -o led.elf led.o

install: led.hex
    avrdude -F -V -c arduino -p ATMEGA328P -P ${PORT} -b 115200 -U flash:w:led.hex

Itu mengatakan bahwa setiap kompilasi C otomatis akan dilakukan dengan avr-gcc dan flag yang ditentukan dalam CFLAGS. Ini secara default akan membuat file hex menggunakan OBJCOPY, yang diatur ke avr, yang bergantung pada file led.elf - jadi untuk mendapatkan file itu ia menjalankan target led.elf, yang menghubungkan file objek led.o dengan pustaka default menggunakan apa pun yang diatur dalam CC. Untuk melakukan itu perlu led.o, dan itu membuatnya secara otomatis menggunakan program yang ditentukan dalam CC dan bendera di CFLAGS. Anda kemudian dapat secara opsional make installyang akan menjalankan avrdudeuntuk menginstal file hex ke dalam chip.

Anda dapat membuatnya lebih generik sehingga Anda dapat menyalinnya ke proyek lain dan membuat perubahan minimum yang diperlukan:

BIN=led
OBJS=led.o test.o

CC=avr-gcc
OBJCOPY=avr-objcopy
CFLAGS=-Os -DF_CPU=16000000UL -mmcu=atmega328p
PORT=/dev/ttyACM0

${BIN}.hex: ${BIN}.elf
    ${OBJCOPY} -O ihex -R .eeprom $< $@

${BIN}.elf: ${OBJS}
    ${CC} -o $@ $^

install: ${BIN}.hex
    avrdude -F -V -c arduino -p ATMEGA328P -P ${PORT} -b 115200 -U flash:w:$<

clean:
    rm -f ${BIN}.elf ${BIN}.hex ${OBJS}

Itu menggunakan "variabel otomatis" dan penggantian nama sederhana. BINberisi "basis" file biner Anda, OBJSberisi daftar file objek. $ @ adalah nama target saat ini, $ <adalah nama prasyarat pertama, dan $ ^ adalah daftar semua prasyarat. Cukup ganti BINdan OBJSsesuaikan. Sebagai bonus saya telah dilemparkan make cleanuntuk menghapus file yang dikompilasi dan hanya meninggalkan Anda dengan sumbernya.

Majenko
sumber
makefile yang diposting memerlukan baris lain di dekat bagian atas; yang mengatakan: '.PHONY: install clean'
user3629249
@ user3629249 Mengapa? Makefile seperti yang diposting berfungsi dengan baik. Anda hanya perlu .PHONY untuk target yang disebut sebagai prasyarat, bukan target yang disebut secara manual.
Majenko
1
@Majenko Ini praktik yang baik untuk membuat target palsu untuk apa pun yang sebenarnya bukan nama file. Jika Anda membuat file bernama installatau file bernama clean(skrip shell, mungkin?), Maka makemungkin berpikir bahwa mereka Up to datedan tidak melakukan apa pun.
wchargin
@WChargin Jika Anda melakukan sesuatu yang gila seperti itu maka Anda layak tidak bekerja. Script shell Anda harus clean.shdan install.shjika Anda harus memilikinya.
Majenko
2

Jawaban yang diterima sangat bagus karena telah memberi saya pelajaran berharga dalam semua jenis alat debugging (avr-objdump -D telah menjadi teman dekat). Yaitu, garis:

${OBJCOPY} -O ihex -R .eeprom $< $@

hilang bendera arsitektur dan harus dibaca

$ {OBJCOPY} -mmcu = atmega328p -O ihex -R. Tetap dari $ <$ @

Tanpa flag arsitektur -mmcu, avr-gcc menebak kami mengkompilasi untuk arsitektur 8515 (pasti tidak) dan ia menghasilkan file .elf tanpa instruksi awal untuk inisialisasi, yaitu tanpa instruksi untuk memanggil fungsi "utama" dll.

Ini menghasilkan perilaku membingungkan karena program sederhana apa pun (mis. Blink) dengan hanya fungsi "utama" berfungsi dengan baik, tetapi jika Anda mendefinisikan fungsi lain sebelum atau setelah "main", ia menjalankan fungsi itu dan tidak pernah memanggil "main" atau restart sepanjang waktu dll.

Saya juga bukan penggemar tertentu menghindari verifikasi jenis MCU yang benar dan program yang diunggah, jadi saya akan menganjurkan untuk tidak menggunakan -F dan -V dan menggunakan -v sebagai gantinya.

Jadi, jawaban yang ditingkatkan dapat:

PKG=led
BIN=${PKG}
OBJS=${PKG}.o
MCU=atmega328p

CC=avr-gcc
OBJCOPY=avr-objcopy
CFLAGS=-Os -DF_CPU=16000000UL -mmcu=${MCU} -Wall
PORT=/dev/ttyACM0

${BIN}.hex: ${BIN}.elf
        ${OBJCOPY} -O ihex $< $@

${BIN}.elf: ${OBJS}
        ${CC} -mmcu=${MCU} -o $@ $^

install: ${BIN}.hex
        avrdude -v -c arduino -p ${MCU} -P ${PORT} -b 115200 -U flash:w:$<

clean:
        rm -f ${BIN}.elf ${BIN}.hex ${OBJS}
Robert Špendl
sumber
Anda menulis: " Tanpa flag arsitektur -mmcu, tebakan avr-gcc kami mengkompilasi untuk arsitektur 8515 ". Sebenarnya ini avr2: "Perangkat 'klasik' dengan memori program hingga 8 KiB."
Edgar Bonet
Saya merujuk pada referensi Atmel atmel.com/webdoc/avrlibcreferencemanual/... Apakah mereka salah?
Robert Špendl
Mungkin maksud mereka MCU AT90S8515 yang, tidak seperti penggantinya (ATmega8515), memiliki arsitektur avr2. Halaman yang Anda tautkan mungkin telah ditulis pada saat "8515" tidak ambigu. Dan mereka tidak menyebutnya "arsitektur", karena hanya satu dari banyak MCU yang berbagi arsitektur avr2.
Edgar Bonet