Makefile cơ bản cho avr-gcc


7

Tôi muốn tạo một makefile để biên dịch các chương trình c cho arduino. Tôi có phần quen thuộc với make nhưng chưa bao giờ sử dụng nó với avr-gcc. Cách đơn giản nhất tôi có thể đặt các lệnh dưới đây trong một tệp thực hiện là gì?

$ 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

Vì đây là một diễn đàn Arduino, nên sẽ chính xác hơn để biên dịch -I/usr/share/arduino/hardware/arduino/cores/arduino -I/usr/share/arduino/hardware/arduino/variants/standardvà liên kết với libcore.a. :-)
Edgar Bonet

Câu trả lời:


5

Không khác gì khi làm việc với Make và bất kỳ hình thức GCC nào khác. Chỉ cần đặt biến CC và biến CFLAGS của bạn tương ứng và hoạt động như bình thường.

Chẳng hạn, tôi vừa gõ cái này lên:

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

Điều đó nói rằng bất kỳ quá trình biên dịch C tự động nào cũng sẽ được thực hiện với avr-gcc và các cờ được chỉ định trong CFLAGS. Theo mặc định, nó sẽ tạo tệp hex bằng OBJCOPY, được đặt thành avr, dựa trên tệp led.elf - vì vậy để có được tệp đó, nó chạy mục tiêu led.elf, liên kết tệp đối tượng led.o với các thư viện mặc định sử dụng bất cứ thứ gì đã được đặt trong CC. Để làm điều đó, nó cần led.o và nó tự động sử dụng chương trình được chỉ định trong CC và các cờ trong CFLAGS. Sau đó, bạn có thể tùy chọn make installsẽ chạy avrdudeđể cài đặt tệp hex vào chip.

Bạn có thể làm cho nó thậm chí còn chung chung hơn để bạn có thể sao chép nó vào các dự án khác và thực hiện các thay đổi tối thiểu cần thiết:

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}

Điều đó sử dụng "biến tự động" và thay thế tên đơn giản. BINchứa "cơ sở" của tệp nhị phân của bạn, OBJSchứa danh sách các tệp đối tượng. $ @ là tên của mục tiêu hiện tại, $ <là tên của điều kiện tiên quyết đầu tiên và $ ^ là danh sách của tất cả các điều kiện tiên quyết. Chỉ cần thay đổi BINOBJScho phù hợp. Như một phần thưởng tôi đã ném vào make cleanđể loại bỏ các tập tin đã biên dịch và chỉ để lại cho bạn nguồn.


makefile được đăng cần một dòng khác gần đầu; có nghĩa là: '.PHONY: cài đặt sạch'
user3629249

@ user3629249 Tại sao? Makefile như được đăng hoạt động hoàn hảo. Bạn chỉ cần .PHONY cho các mục tiêu được gọi là điều kiện tiên quyết, không phải mục tiêu được gọi thủ công.
Majenko

1
@Majenko Thực hành tốt để tạo mục tiêu giả mạo cho bất kỳ thứ gì không thực sự là tên tệp. Nếu bạn tạo một tệp được gọi installhoặc một tệp có tên clean(shell script, có lẽ?), Thì makecó thể nghĩ rằng chúng Up to datevà không làm gì cả.
wchargein

@WChargin Nếu bạn làm một việc gì đó như vậy thì bạn xứng đáng không làm việc. Kịch bản shell của bạn nên clean.shinstall.shnếu bạn phải có chúng.
Majenko

2

Câu trả lời được chấp nhận là rất tốt vì nó đã cho tôi một bài học quý giá về tất cả các loại công cụ gỡ lỗi (avr-objdump -D đã trở thành một người bạn thân). Cụ thể, dòng:

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

thiếu cờ kiến ​​trúc và nên đọc

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

Không có cờ kiến ​​trúc -mmcu, avr-gcc đoán chúng tôi đang biên dịch cho kiến ​​trúc 8515 (chắc chắn là không) và nó tạo ra tệp .elf mà không có hướng dẫn ban đầu để khởi tạo, tức là không có hướng dẫn để gọi hàm "chính", v.v.

Điều này dẫn đến hành vi khó hiểu vì bất kỳ chương trình đơn giản nào (ví dụ nhấp nháy) chỉ có chức năng "chính" hoạt động hoàn hảo, nhưng nếu bạn xác định chức năng khác trước hoặc sau "chính", nó sẽ chạy chức năng đó và không bao giờ gọi "chính" hoặc nó khởi động lại mọi lúc

Tôi cũng không phải là một người hâm mộ đặc biệt tránh việc xác minh loại MCU chính xác và chương trình được tải lên, vì vậy tôi ủng hộ không sử dụng -F và -V và sử dụng -v thay vào đó.

Vì vậy, câu trả lời được cải thiện có thể là:

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}

Bạn đã viết: Không có cờ kiến ​​trúc -mmcu, avr-gcc đoán chúng tôi đang biên dịch cho 8515 kiến ​​trúc . Trên thực tế, đó là avr2: các thiết bị 'Cổ điển' có bộ nhớ chương trình lên tới 8 KiB.
Edgar Bonet

Tôi đã tham khảo tài liệu tham khảo Atmel tạimel.com/webdoc/avrlibcreferencemanual/ khăn Có phải họ đã nhầm?
Robert pendl

Có lẽ họ có nghĩa là AT90S8515 MCU, không giống như sự thay thế của nó (ATmega8515), có kiến ​​trúc avr2. Trang bạn liên kết đến có thể đã được viết trong một thời gian khi mà 85 85 không phải là mơ hồ. Và họ không gọi nó là kiến ​​trúc của người khác, vì đó chỉ là một trong số nhiều MCU chia sẻ kiến ​​trúc avr2.
Edgar Bonet
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.