Программирование AVR avr-gcc: опции компилятора C для микроконтроллеров AVR Fri, October 11 2024  

Поделиться

Нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.

avr-gcc: опции компилятора C для микроконтроллеров AVR Печать
Добавил(а) microsin   

В этой статье рассматриваются специфичные для AVR особенности использования инструментов GNU (перевод документации по компилятору C avr-gcc, ассемблеру avr-as, линкеру/компоновщику avr-ld). Обычно документация для этих инструментов довольно объемная, и поставляется в виде файлов texinfo. Опции командной строки более детально описаны в соответствующей документации.

[Опции компилятора C avr-gcc]

Опции, специфичные для разновидности микроконтроллера AVR (Machine-specific options)

Интерфейс компилятора C avr-gcc распознает опции, относящиеся к микроконтроллеру. В дополнение к макросам препроцессора, показанных в таблице далее, препроцессор также определяет макросы __AVR и __AVR__ (со значением 1), когда компилируется цель AVR (AVR target). Макросы AVR будут определены в стандартном режиме gnu89 (по умолчанию) и в режиме gnu99, но не будут определены в режимах c89 и c99.

-mmcu=architecture

В поле architecture опции закодирован тип микроконтроллера. Сейчас известны следующие архитектуры:

Архитектура Макросы Описание
avr1 __AVR_ARCH__=1
__AVR_ASM_ONLY__
__AVR_2_BYTE_PC__ (2)
Простое ядро CPU, поддерживается только ассемблер
avr2 __AVR_ARCH__=2
__AVR_2_BYTE_PC__ (2)
"Классическое" ядро CPU, до 8 килобайт ROM
avr25 (1) __AVR_ARCH__=25
__AVR_HAVE_MOVW__ (1)
__AVR_HAVE_LPMX__ (1)
__AVR_2_BYTE_PC__ (2)
"Классическое" ядро CPU с поддержкой инструкций 'MOVW' и 'LPM Rx, Z[+]', до 8 килобайт ROM
avr3 __AVR_ARCH__=3
__AVR_MEGA__ (5)
__AVR_HAVE_JMP_CALL__ (4)
__AVR_2_BYTE_PC__ (2)
"Классическое" ядро CPU, от 16 до 64 килобайт ROM
avr31 __AVR_ARCH__=31
__AVR_MEGA__ (5)
__AVR_HAVE_JMP_CALL__ (4)
__AVR_HAVE_RAMPZ__ (4)
__AVR_HAVE_ELPM__ (4)
__AVR_2_BYTE_PC__ (2)
"Классическое" ядро CPU, 128 килобайт ROM
avr35 (3) __AVR_ARCH__=35
__AVR_MEGA__ (5)
__AVR_HAVE_JMP_CALL__ (4)
__AVR_HAVE_MOVW__ (1)
__AVR_HAVE_LPMX__ (1)
__AVR_2_BYTE_PC__ (2)
"Классическое" ядро CPU с поддержкой инструкций 'MOVW' и 'LPM Rx, Z[+]', от 18 до 64 килобайт ROM
avr4 __AVR_ARCH__=4
__AVR_ENHANCED__ (5)
__AVR_HAVE_MOVW__ (1)
__AVR_HAVE_LPMX__ (1)
__AVR_HAVE_MUL__ (1)
__AVR_2_BYTE_PC__ (2)
"Усиленное (enhanced)" ядро CPU, до 8 килобайт ROM
avr5 __AVR_ARCH__=5
__AVR_MEGA__ (5)
__AVR_ENHANCED__ (5)
__AVR_HAVE_JMP_CALL__ (4)
__AVR_HAVE_MOVW__ (1)
__AVR_HAVE_LPMX__ (1)
__AVR_HAVE_MUL__ (1)
__AVR_2_BYTE_PC__ (2)
"Усиленное (enhanced)" ядро CPU, от 16 до 64 килобайт ROM
avr51 __AVR_ARCH__=51
__AVR_MEGA__ (5)
__AVR_ENHANCED__ (5)
__AVR_HAVE_JMP_CALL__ (4)
__AVR_HAVE_MOVW__ (1)
__AVR_HAVE_LPMX__ (1)
__AVR_HAVE_MUL__ (1)
__AVR_HAVE_RAMPZ__ (4)
__AVR_HAVE_ELPM__ (4)
__AVR_HAVE_ELPMX__ (4)
__AVR_2_BYTE_PC__ (2)
"Усиленное (enhanced)" ядро CPU, 128 килобайт ROM
avr6 (2) __AVR_ARCH__=6
__AVR_MEGA__ (5)
__AVR_ENHANCED__ (5)
__AVR_HAVE_JMP_CALL__ (4)
__AVR_HAVE_MOVW__ (1)
__AVR_HAVE_LPMX__ (1)
__AVR_HAVE_MUL__ (1)
__AVR_HAVE_RAMPZ__ (4)
__AVR_HAVE_ELPM__ (4)
__AVR_HAVE_ELPMX__ (4)
__AVR_3_BYTE_PC__ (2)
"Усиленное (enhanced)" ядро CPU, 256 килобайт ROM

Примечания:
(1) Появилось в GCC 4.2
(2) Неофициальный патч для GCC 4.1
(3) Появилось в GCC 4.2.3
(4) Появилось в GCC 4.3
(5) Устарело.

По умолчанию генерируется код для архитектуры avr2.

Внимание: когда используется опция -mmcu=architecture, но не опция -mmcu=MCU, подключаемый файл <avr/io.h> работать не будет, поскольку он не сможет выбрать определения (definitions) для конкретного типа микроконтроллера AVR.

-mmcu=MCU type

Сейчас avr-gcc понимает следующие типы микроконтроллеров (MCU types), перечисленные в таблице. В таблице также перечислены соответствующие типы архитектур для указанных микроконтроллеров, и показаны макросы препроцессора, которые будут заданы при использовании опции -mmcu.

Внимание, очень важно: тип микроконтроллера нужно указывать в нижнем регистре, т. е. маленькими буквами! Не надо умничать, и задавать что-то типа -mmcu=ATmega32U4, компилятор avr-gcc Вас не поймет и выдаст ошибку (надо было задать -mmcu=atmega32u4):

myfile.c:1:0: error: unrecognized argument to -mmcu= option: 'ATmega32U4'
myfile.c:1:0: note: See --target-help for supported MCUs

Итак, поддерживаемые имена MCU для опции -mmcu:

Архитектура Имя MCU

Макрос

avr1 at90s1200 __AVR_AT90S1200__
attiny11 __AVR_ATtiny11__
attiny12 __AVR_ATtiny12__
attiny15 __AVR_ATtiny15__
attiny28 __AVR_ATtiny28__
avr2 at90s2313 __AVR_AT90S2313__
at90s2323 __AVR_AT90S2323__
at90s2333 __AVR_AT90S2333__
at90s2343 __AVR_AT90S2343__
attiny22 __AVR_ATtiny22__
attiny26 __AVR_ATtiny26__
at90s4414 __AVR_AT90S4414__
at90s4433 __AVR_AT90S4433__
at90s4434 __AVR_AT90S4434__
at90s8515 __AVR_AT90S8515__
at90c8534 __AVR_AT90C8534__
at90s8535 __AVR_AT90S8535__
avr2/avr25 (1) at86rf401 __AVR_AT86RF401__
ata6289 __AVR_ATA6289__
attiny13 __AVR_ATtiny13__
attiny13a __AVR_ATtiny13A__
attiny2313 __AVR_ATtiny2313__
attiny2313a __AVR_ATtiny2313A__
attiny24 __AVR_ATtiny24__
attiny24a __AVR_ATtiny24A__
attiny25 __AVR_ATtiny25__
attiny261 __AVR_ATtiny261__
attiny261a __AVR_ATtiny261A__
attiny4313 __AVR_ATtiny4313__
attiny43u __AVR_ATtiny43U__
attiny44 __AVR_ATtiny44__
attiny44a __AVR_ATtiny44A__
attiny45 __AVR_ATtiny45__
attiny461 __AVR_ATtiny461__
attiny461a __AVR_ATtiny461A__
attiny48 __AVR_ATtiny48__
attiny84 __AVR_ATtiny84__
attiny84a __AVR_ATtiny84A__
attiny85 __AVR_ATtiny85__
attiny861 __AVR_ATtiny861__
attiny861a __AVR_ATtiny861A__
attiny87 __AVR_ATtiny87__
attiny88 __AVR_ATtiny88__
avr3 atmega603 __AVR_ATmega603__
at43usb355 __AVR_AT43USB355__
avr3/avr31 (3) atmega103 __AVR_ATmega103__
at43usb320 __AVR_AT43USB320__
avr3/avr35 (2) at90usb82 __AVR_AT90USB82__
at90usb162 __AVR_AT90USB162__
atmega8u2 __AVR_ATmega8U2__
atmega16u2 __AVR_ATmega16U2__
atmega32u2 __AVR_ATmega32U2__
attiny167 __AVR_ATtiny167__
avr3 at76c711 __AVR_AT76C711__
avr4 atmega48 __AVR_ATmega48__
atmega48a __AVR_ATmega48A__
atmega48p __AVR_ATmega48P__
atmega8 __AVR_ATmega8__
atmega8515 __AVR_ATmega8515__
atmega8535 __AVR_ATmega8535__
atmega88 __AVR_ATmega88__
atmega88a __AVR_ATmega88A__
atmega88p __AVR_ATmega88P__
atmega88pa __AVR_ATmega88PA__
atmega8hva __AVR_ATmega8HVA__
at90pwm1 __AVR_AT90PWM1__
at90pwm2 __AVR_AT90PWM2__
at90pwm2b __AVR_AT90PWM2B__
at90pwm3 __AVR_AT90PWM3__
at90pwm3b __AVR_AT90PWM3B__
at90pwm81 __AVR_AT90PWM81__
avr5 at90can32 __AVR_AT90CAN32__
at90can64 __AVR_AT90CAN64__
at90pwm216 __AVR_AT90PWM216__
at90pwm316 __AVR_AT90PWM316__
at90scr100 __AVR_AT90SCR100__
at90usb646 __AVR_AT90USB646__
at90usb647 __AVR_AT90USB647__
at94k __AVR_AT94K__
atmega16 __AVR_ATmega16__
atmega161 __AVR_ATmega161__
atmega162 __AVR_ATmega162__
atmega163 __AVR_ATmega163__
atmega164a __AVR_ATmega164A__
atmega164p __AVR_ATmega164P__
atmega165 __AVR_ATmega165__
atmega165a __AVR_ATmega165A__
atmega165p __AVR_ATmega165P__
atmega168 __AVR_ATmega168__
atmega168a __AVR_ATmega168A__
atmega168p __AVR_ATmega168P__
atmega169 __AVR_ATmega169__
atmega169a __AVR_ATmega169A__
atmega169p __AVR_ATmega169P__
atmega169pa __AVR_ATmega169PA__
atmega16a __AVR_ATmega16A__
atmega16hva __AVR_ATmega16HVA__
atmega16hva2 __AVR_ATmega16HVA2__
atmega16hvb __AVR_ATmega16HVB__
atmega16hvbrevb __AVR_ATmega16HVBREVB__
atmega16m1 __AVR_ATmega16M1__
atmega16u4 __AVR_ATmega16U4__
atmega32 __AVR_ATmega32__
atmega323 __AVR_ATmega323__
atmega324a __AVR_ATmega324A__
atmega324p __AVR_ATmega324P__
atmega324pa __AVR_ATmega324PA__
atmega325 __AVR_ATmega325__
atmega325a __AVR_ATmega325A__
atmega325p __AVR_ATmega325P__
atmega3250 __AVR_ATmega3250__
atmega3250a __AVR_ATmega3250A__
atmega3250p __AVR_ATmega3250P__
atmega328 __AVR_ATmega328__
atmega328p __AVR_ATmega328P__
atmega329 __AVR_ATmega329__
atmega329a __AVR_ATmega329A__
atmega329p __AVR_ATmega329P__
atmega329pa __AVR_ATmega329PA__
atmega3290 __AVR_ATmega3290__
atmega3290a __AVR_ATmega3290A__
atmega3290p __AVR_ATmega3290P__
atmega32c1 __AVR_ATmega32C1__
atmega32hvb __AVR_ATmega32HVB__
atmega32hvbrevb __AVR_ATmega32HVBREVB__
atmega32m1 __AVR_ATmega32M1__
atmega32u4 __AVR_ATmega32U4__
atmega32u6 __AVR_ATmega32U6__
atmega406 __AVR_ATmega406__
atmega64 __AVR_ATmega64__
atmega640 __AVR_ATmega640__
atmega644 __AVR_ATmega644__
atmega644a __AVR_ATmega644A__
atmega644p __AVR_ATmega644P__
atmega644pa __AVR_ATmega644PA__
atmega645 __AVR_ATmega645__
atmega645a __AVR_ATmega645A__
atmega645p __AVR_ATmega645P__
atmega6450 __AVR_ATmega6450__
atmega6450a __AVR_ATmega6450A__
atmega6450p __AVR_ATmega6450P__
atmega649 __AVR_ATmega649__
atmega649a __AVR_ATmega649A__
atmega6490 __AVR_ATmega6490__
atmega6490a __AVR_ATmega6490A__
atmega6490p __AVR_ATmega6490P__
atmega649p __AVR_ATmega649P__
atmega64c1 __AVR_ATmega64C1__
atmega64hve __AVR_ATmega64HVE__
atmega64m1 __AVR_ATmega64M1__
m3000 __AVR_M3000__
avr5/avr51 (3) at90can128 __AVR_AT90CAN128__
at90usb1286 __AVR_AT90USB1286__
at90usb1287 __AVR_AT90USB1287__
atmega128 __AVR_ATmega128__
atmega1280 __AVR_ATmega1280__
atmega1281 __AVR_ATmega1281__
atmega1284p __AVR_ATmega1284P__
avr6 atmega2560 __AVR_ATmega2560__
atmega2561 __AVR_ATmega2561__
avrxmega2 atxmega16a4 __AVR_ATxmega16A4__
atxmega16d4 __AVR_ATxmega16D4__
atxmega32a4 __AVR_ATxmega32A4__
atxmega32d4 __AVR_ATxmega32D4__
avrxmega4 atxmega64a3 __AVR_ATxmega64A3__
atxmega64d3 __AVR_ATxmega64D3__
avrxmega5 atxmega64a1 __AVR_ATxmega64A1__
atxmega64a1u __AVR_ATxmega64A1U__
avrxmega6 atxmega128a3 __AVR_ATxmega128A3__
atxmega128d3 __AVR_ATxmega128D3__
atxmega192a3 __AVR_ATxmega192A3__
atxmega192d3 __AVR_ATxmega192D3__
atxmega256a3 __AVR_ATxmega256A3__
atxmega256a3b __AVR_ATxmega256A3B__
atxmega256d3 __AVR_ATxmega256D3__
avrxmega7 atxmega128a1 __AVR_ATxmega128A1__
atxmega128a1u __AVR_ATxmega128A1U__
avrtiny10 attiny4 __AVR_ATtiny4__
attiny5 __AVR_ATtiny5__
attiny9 __AVR_ATtiny9__
attiny10 __AVR_ATtiny10__
attiny20 __AVR_ATtiny20__
attiny40 __AVR_ATtiny40__

Примечания:
(1) Архитектура 'avr25' появилась в GCC 4.2
(2) Архитектура 'avr35' появилась в GCC 4.2.3
(3) Архитектуры 'avr31' и 'avr51' появились в in GCC 4.3

-morder1
-morder2

Изменение порядка назначения регистров. По умолчанию порядок следующий:

r24, r25, r18, r19, r20, r21, r22, r23, r30, r31, r26, r27, r28, r29, r17, r16, r15, r14, r13, r12, r11, r10, r9, r8, r7, r6, r5, r4, r3, r2, r0, r1

order1 использует следующий порядок:

r18, r19, r20, r21, r22, r23, r24, r25, r30, r31, r26, r27, r28, r29, r17, r16, r15, r14, r13, r12, r11, r10, r9, r8, r7, r6, r5, r4, r3, r2, r0, r1

order2 использует следующий порядок:

r25, r24, r23, r22, r21, r20, r19, r18, r30, r31, r26, r27, r28, r29, r17, r16, r15, r14, r13, r12, r11, r10, r9, r8, r7, r6, r5, r4, r3, r2, r1, r0

-mint8

Подразумевает, что тип int соответствует 8-битному целому (8-bit integer). Имейте в виду, что библиотекой avr-libc реально не поддерживается такой режим, так что он обычно не должен использоваться. По умолчанию в качестве int используются 16-битные целые числа (16-bit integers).

-mno-interrupts

Генерирует код, который меняет указатель стека (stack pointer) без запрета прерываний. Обычно состояние регистра статуса SREG (status register SREG) сохраняется во временном регистре, прерывания запрещаются в во время изменения указателя стека, и значение регистра SREG восстанавливается. Если указать эту опцию, также будет определен макрос препроцессора __NO_INTERRUPTS__ в значении 1.

-mcall-prologues

Для функции пролога/эпилога (function prologue/epilogue) будут использоваться подпрограммы (subroutines). Для сложных функций, которые используют много регистров (состояние которых нужно сохранить/восстановить на входе/выходе функции), эта опция будет экономить некоторое количество памяти кода программ взамен на некоторое снижение быстродействия (increase execution time).

-mtiny-stack

"Маленький стек". В указателе стека изменяются только младшие 8 бит.

-mno-tablejump

Эта опция устарела, используйте вместо неё опцию -fno-jump-tables.

-mshort-calls

Для микроконтроллеров с памятью размером >8K будут использованы команды перехода rjmp/rcall (имеющие ограниченный адресный диапазон). На архитектурах avr2 и avr4 (у которых размер памяти flash меньше 8 кбайт) это всегда имеет место. На архитектурах avr3 и avr5 вызовы подпрограмм и переходы по адресу, которые выходят за этот диапазон, будут по умолчанию использовать инструкции jmp/call, которые могут закрыть все адресное пространство, однако это потребует большего размера flash ROM и увеличивает время выполнения.

-mrtl

Будет выведен дамп внутреннего результата компиляции (internal compilation result, так называемый RTL) в комментариях к генерируемому коду ассемблера. Эта опция используется для отладки avr-gcc.

-msize

Будет выведен дамп адреса, размера, и относительной стоимости каждого оператора в комментариях к генерируемому коду ассемблера. Эта опция используется для отладки avr-gcc.

-mdeb

Генерирует вывод некоторой отладочной информации в поток stderr (обычно консоль).

Выборочное описание некоторых главных опций компилятора (general compiler options)

Следующие общие опции компилятора gcc (general gcc options) могут представлять некоторый интерес для пользователей AVR.

-On

Уровень оптимизации n. Увеличение числа n означает увеличение степени оптимизации, при этом уровень 0 полностью отключает оптимизацию (это является поведением по умолчанию, когда опция -O отсутствует). Специальная опция -Os означает включение всех оптимизаций -O2, которые не должны привести к увеличению размера кода.

Имейте в виду, что при использовании -O3 компилятор gcc будет пытаться перевести во встраиваемый код (inline) все "простые" функции. Для микроконтроллеров AVR (AVR target) это приведет к пагубному росту используемого пространства под код. Единственно полезная оптимизация, которая также включается в -O3, является -frename-registers, однако эту опцию лучше активировать отдельно вручную.

Если просто указать опцию -O, то это будет эквивалентно указанию опции -O1.

Имейте в виду, что полное выключение оптимизации предотвратит выдачу некоторых предупреждений, так как генерация их зависит от шагов анализа кода, которые будут выполняться только при оптимизации (нерабочий код unreachable code, неиспользуемые переменные unused variables). См. также соответствующий вопрос в FAQ [1], который относится к отладке оптимизированного кода.

-Wa,assembler-options
-Wl,linker-options

Передать список опций ассемблеру и линкеру соответственно.

-g

Сгенерировать отладочную информацию (debugging information), которая может быть использована отладчиком avr-gdb.

-ffreestanding

Предполагается использование "freestanding" environment (независимое окружение), что соответствует стандарту C. Это отключит все автоматически генерируемые встроенные функции (которые все еще можно вызвать с префиксом __builtin_, предварительно добавленным к действительному имени функции). Это также заставляет компилятор не жаловаться, когда функция main() декларируется как возвращающая void, что больше соответствует среде выполнения микроконтроллера, где приложение не может предоставить обоснованный код возврата для среды выполнения (в большинстве случаев из функции main() никогда не происходит возврат). Однако это также отключит все оптимизации, обычно выполняемые компилятором, который предполагает, что функции, известные под определенным именем, ведут себя как описано в стандарте. Например, E. g., применение функции strlen() к литеральной строке обычно заставляет компилятор просто заменить вызов функции действующей длиной строки, тогда как с опцией -ffreestanding, во время выполнения всегда будет вызвана strlen().

-funsigned-char

Заменяет любой неквалифицированный специально тип char на unsigned char. Без этой опции по умолчанию char соответствует signed char.

-funsigned-bitfields

Заменяет любой неквалифицированный специально тип битовых полей (unqualified bitfield type) на беззнаковый (unsigned). По умолчанию он со знаком (signed).

-fshort-enums

Выделение перечислимому типу (enum) только такое количество байтов, сколько требуется для объявленного диапазона возможных значений. В частности, перечислимый тип (enum type) будет эквивалентен самому маленькому целочисленному типу, который имеет достаточный размер.

-fpack-struct

Плотная упаковка всех полей структуры (structure members) без пустого выравнивающего байтового пространства.

-fno-jump-tables

Не генерировать инструкций табличного перехода (tablejump instructions). По умолчанию таблицы переходов могут быть использованы для оптимизации операторов switch. Когда эта возможность выключена, вместо таблицы переходов будет использована последовательность команд сравнения. Таблицы переходов (Jump tables) обычно в среднем работают быстрее, однако в частности для операторов switch, которые должны делать переход по метке default, это может привести к некоторой бесполезной потере памяти кода (flash memory).

Внимание: инструкции табличного перехода tablejump используют команду ассемблера LPM для доступа к таблицам перехода. Всегда используйте -fno-jump-tables, если Вы компилируете бутлоадер (bootloader) для устройств, которые имеют больше 64 килобайта памяти кода.

[Опции для ассемблера avr-as]

Опции, специфичные для разновидности микроконтроллера AVR (Machine-specific assembler options)

-mmcu=architecture
-mmcu=MCU name

Ассемблер avr-as понимает те же самые опции -mmcu=, используемые для avr-gcc. По умолчанию подразумевается архитектура avr2, однако это может быть отменено использованием подходящей псевдоинструкции .arch внутри исходного кода программы ассемблера.

-mall-opcodes

Выключает проверку кода операций (opcode checking) для действующего типа микроконтроллера (actual MCU type) и позволяет ассемблировать любой возможный для AVR код операции (opcode).

-mno-skip-bug

Отключает выдачу предупреждения, когда происходит попытка пропуска команды/инструкции, состоящей из 2 слов (2-word instruction) с командой CPSE/SBIC/SBIS/SBRC/SBRS. Ранее выпущенные микроконтроллеры AVR пострадали от аппаратной ошибки, из-за которой эти инструкции не могли быть должным образом пропущены.

-mno-wrap

Запрет использования повторения инструкций RJMP/RCALL для перехода по целевому адресу для микроконтроллеров, у которых память кода больше 8 килобайт.

--gstabs

Генерировать символы отладки .stabs для строк исходного кода ассемблера. Это позволит отладчику avr-gdb выполнять трассировку по исходному коду ассемблера. Эта опция не должна использоваться, когда ассемблируются исходные коды, которые были сгенерированы компилятором C; эти файлы уже содержат соответствующую информацию о номерах строк файлов исходного кода C.

-a[cdhlmns=file]

Включить листинг ассемблера. Подопции следующие:

c пропустить ложные условные выражения (omit false conditionals)
d пропустить директивы отладки (omit debugging directives)
h включить код высокого уровня (include high-level source)
l включить код ассемблера (include assembly)
m включить развертывание кода макросов (include macro expansions)
n пропустить обработку форм (omit forms processing)
s включить символы (include symbols)
=file установить имя для файла листинга

Различные подопции можно комбинировать в один список опций -a; в этом случае =file должна быть последней в этом списке.

Примеры опций ассемблера, передаваемых через компилятор C

Помните, что опции ассемблера могут быть переданы через интерфейс (командную строку) компилятора C опцией -Wa (см. выше). Так, чтобы включить исходный код C в файл листинга foo.lst, когда компилируется foo.c, должна использоваться следующая командная строка:

$ avr-gcc -c -O foo.c -o foo.o -Wa,-ahls=foo.lst

Чтобы сначала передать ассемблерный файл через препроцессор C и дать команду ассемблеру сгенерировать отладочную информацию с номерами строк для него, нужно использовать следующую командную строку:

$ avr-gcc -c -x assembler-with-cpp -o foo.o foo.S -Wa,--gstabs

Имейте в виду, что системы Unix имеют чувствительную к регистру символов файловые системы (case-distinguishing file systems), так что указание имени файла с суффиксом (расширением) .S (буква S в верхнем регистре, upper-case) сделает автоматическое подразумевание компилятором -x assembler-with-cpp, в то время как использование .s передало бы файл напрямую ассемблеру (не будет производится препроцессинг). При переносе проектов с Linux на Windows (для компиляции через avr-gcc пакета WinAVR) регистр имен файлов служит частым источником неприятных ошибок, требующих ручной корректировки makefile.

Для того, чтобы скомпилировать исходный код C не в объектный файл, а в код ассемблера, применяется опция -Wall:

$ avr-gcc -Wall -c module.c

[Управление линковщиком avr-ld]

Выбранные опции линкера

Так как для линкера avr-ld нет специфичных для микроконтроллера AVR опций (machine-specific options), то пользователя AVR может заинтересовать некоторое количество стандартных опций.

-lname

Указание на использование архива библиотеки с именем libname.a, и использования его для разрешения нераспознанных в настоящий момент символов. Файл библиотеки будет искаться по пути, состоящем из встроенных записей, указанных во время компиляции (например, /usr/local/avr/lib на системах Unix), возможно расширенных записями пути, указанными опциями -L (которые в командной строке должны предшествовать опциям -l).

-Lpath

Дополнительный путь для поиска архивных библиотек, запрашиваемых опциями -l.

--defsym symbol=expr

Определение глобального символа symbol, используя для его значения выражение expr.

-M

Напечатать карту линковки (linker map) в stdout (обычно консоль).

-Map mapfile

Вывести карту линковки (linker map) в файл mapfile.

--cref

Вывести таблицу перекрестных ссылок (cross reference table) в файл карты линковки map file (в случае наличия опции -Map), или в stdout (обычно консоль).

--section-start sectionname=org

Начать секцию с именем sectionname по абсолютному адресу org.

-Tbss org
-Tdata org
-Ttext org

Начать соответственно секцию bss, data, или text по адресу org.

-T scriptfile

Использование файла scriptfile в качестве скрипта линковки (linker script), который заменит скрипт линковки по умолчанию (default linker script). Скрипты линковки по умолчанию размещены в местах, которые зависят от системы (например /usr/local/avr/lib/ldscripts на системах Unix), и состоит из имени архитектуры AVR (от avr2 до avr5) с добавленным суффиксом .x. Скрипты линковки описывают, как различные секции памяти должны быть слинкованы друг с другом.

Передача опций линкера (компоновщика) через компилятор C

По умолчанию все неизвестные аргументы командной строки (unknown non-option arguments) компилятора avr-gcc (например, все аргументы имени файла, которые не имеют суффикса, поддерживаемого avr-gcc) передаются напрямую линкеру. Таким образом все файлы, оканчивающиеся на .o (объектные файлы) и на .a (объектные библиотеки) передаются линкеру.

Системные библиотеки обычно передаются не по их явном имени файла, а через применение опции -l, которая использует аббревиатурную форму имени файла архива (см. выше). Линкер avr-libc поставляется с двумя системными библиотеками libc.a и libm.a. В то время как стандартная библиотека libc.a будет всегда использоваться для поиска нераспознанных ссылок (unresolved references), когда линкер был запущен через командную строку компилятора C (например, всегда подразумевается неявная опция -lc), библиотека математики libm.a нуждается в явном запросе с использованием -lm. См. также запись в FAQ [2], в котором это объясняется подробнее.

По сложившейся традиции Makefiles использует макрос типа LDLIBS для отслеживания -l (и возможно -L) опций, которые должны быть добавлены только к командной строке компилятора C только тогда, когда линкуется конечный бинарный файл. В отличие от него макрос LDFLAGS используется для хранения других опций командной строки для компилятора C, которые должны быть переданы как опции во время стадии линковки. Разница состоит в том, какие опции будут помещены раньше в командную строку, в то время как библиотеки должны быть помещены в конец, так как они должны использоваться только для того, чтобы разрешить глобальные символы, которые все еще не разрешены в этой точке сборки.

Специфические флаги линкера можно передать компилятору C через командную строку с использованием опции -Wl (см. выше). Эта опция требует, чтобы не было никаких добавленных пробелов в этой опции линкера, в то время как некоторые опции линкера выше (наподобие -Map или --defsym) требуют пробелов. В этих ситуациях пробелы можно заменить эквивалентными знаками минуса. Например, следующая командная строка может использоваться для компиляции foo.c в исполняемый файл, и для получения карты линковки (link map), которая содержит список перекрестных ссылок (cross-reference list) в файле foo.map:

$ avr-gcc -O -o foo.out -Wl,-Map=foo.map -Wl,--cref foo.c

Альтернативно запятая как заполнитель будет заменена пробелом перед передачей прежде, чем будет передана компоновщику. Например, для устройства с внешней SRAM должна использоваться следующая командная строка, которая укажет компоновщику поместить сегмент данных по адресу 0x2000 в SRAM:

$ avr-gcc -mmcu=atmega128 -o foo.out -Wl,-Tdata,0x802000

См. документацию по секции данных (data section [3]) чтобы стало ясно, для чего нужно 0x800000 добавить к действительному значению адреса. Имейте в виду, что стек все еще останется во внутреннем RAM благодаря символу __stack, который предоставлен кодом запуска среды выполнения. Вероятно, что это все равно хорошая идея (так как доступ к внутренней RAM быстрее), и даже требуемый для некоторых ранних микроконтроллеров, которые имели аппаратные ошибки, из-за которых нельзя было использовать стек во внешнем RAM. Обратите внимание также, что куча heap для malloc() будет все еще размещена после всех переменных в секции данных (data section), так что в этой ситуации не будет коллизии stack/heap.

Чтобы поменять место размещения стека по умолчанию (в верхней части внутренней RAM), можно поменять значение символа __stack в командной строке компоновщика. Поскольку компоновщик обычно вызывается через командную строку компилятора (compiler frontend), этого можно добиться использованием опции компилятора наподобие

-Wl,--defsym=__stack=0x8003ff

Эта опция сделает код, который использует пространство для стека начиная с адреса RAM 0x3ff, вниз. Тогда доступный размер области стека зависит от нижней границы адреса внутреннего RAM для конкретной модели микроконтроллера AVR. Приложение (программа firmware AVR) обязана удостовериться, что стек не вырос за пределы границы, а также должна принять меры, чтобы стек не столкнулся с памятью, выделенной под переменные компилятором (секции .data и .bss).

[Ссылки]

1. Why does the PC randomly jump around when single-stepping through my program in avr-gdb? site:nongnu.org - почему счетчик команд PC случайно перепрыгивает по коду, когда выполняется пошаговое выполнение моей программы в avr-gdb?
2. I get "undefined reference to..." for functions like "sin()" site:nongnu.org - я получил сообщение "undefined reference to..." для функции наподобие "sin()".
3. The .data Section site:nongnu.org - описание секции .data.

 

Добавить комментарий


Защитный код
Обновить

Top of Page