Шаблон программы
Обычно в программировании принято в качестве простейшей программы использовать программу, выводящую приветствие, например, "Hello, World!". В программировании микроконтроллеров это уже слишком сложная программа, чтобы быть простейшей, поэтому в качестве простейшей программы напишем программу, которая ничего не делает - создадим так называемый шаблон программы.
В случае языка программирования C шаблон программы для микроконтроллера выглядит следующим образом:
int main()
{
/* TODO: Код инициализации программы и периферийных устройств микроконтроллера */
while (1) /* Бесконечный цикл */
{
/* TODO: Код основного цикла программы */
}
}
Сохраним этот код в файл с названием empty.c.
Скомпилируем его:
avr-gcc empty.c
Компилятор создал в директории файл с названием a.out. Формат файла ELF, и поэтому для удобства укажем компилятору название файла для вывода empty.elf:
avr-gcc -o empty.elf empty.c
Просмотрим информацию о содержимом файла empty.elf с помощью утилиты avr-objdump:
avr-objdump -x empty.elf
Программа avr-objdump сообщает, что файл состоит из одной секции - c названием .text, стартовый адрес секции 0, размер секции 0xA, то есть 10 байт.
Дизассемблируем файл empty.elf командой:
avr-objdump -d empty.elf
Вот что сообщила мне утилита avr-objdump:
Disassembly of section .text:
00000000 <main>:
0: df 93 push r29
2: cf 93 push r28
4: cd b7 in r28, 0x3d ; 61
6: de b7 in r29, 0x3e ; 62
8: ff cf rjmp .-2 ; 0x8 <__zero_reg__+0x7>
Как видно из приведённого дампа шаблон программы и в самом деле ничего не делает, только сохраняет содержимое регистровой пары r28:r29 на стеке и сохраняет адрес вершины стека в этой регистровой паре, после чего программа начинает выполнять бесконечный цикл.
Между тем, даташит сообщает нам, что в начале памяти программ должна бы находиться таблица векторов прерываний. Но она отсутствует, поскольку мы не указали компилятору микроконтроллер, для которого эта программа написана. Сделаем это с помощью ключа -mmcu, указав в качестве параметра название микроконтроллера, например для ATmega16 это будет atmega16:
avr-gcc -o empty.elf -mmcu=atmega16 empty.c
Дизассемблируем полученный ELF. Как видно из листинга, код заметно вырос - добавились таблица векторов прерываний, функции __ctors_end, __bad_interrupt, __exit и __stop_program.
Автор: Андрей Шаройко <vanyamboe@gmail.com>