В этой статье рассматриваются специфичные для 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. |