Шаблон программы

Обычно в программировании принято в качестве простейшей программы использовать программу, выводящую приветствие, например, "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>