Программирование мк avr на языке assembler в среде linux

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

По умолчанию все неизвестные аргументы “не опции” в командной строке avr-gcc (то есть все аргументы “имена файлов”, у которых нет суффиксов, обрабатываемых компилятором avr-gcc) передаются напрямую компоновщику. Таким образом, все файлы, заканчивающиеся на .o (библиотеки объектных модулей), предоставляются компоновщику.

Условно makefile’ы используют макрос сборки , чтобы следить за опциями -l (и возможно -L), которые должны быть добавлены в командную строку Си компилятора только при компоновке конечного двоичного кода. А макрос используется, чтобы записать другие опции командной строки Си компилятора, которые должны быть переданы как опции во время этапа компоновки. Отличие этих опций, размещенных ранее в командной строке, в том, что библиотеки включаются в её конце, так как они должны быть использованы, чтобы определить глобальные символы до сих пор еще неопределенные на данный момент.

Специальные флаги компоновщика могут быть переданы из командной строки Си компилятора, используя опцию компилятора -Wl (смотрите страницу 1 раздела). Эта опция требует отсутствия пробелов в добавленных опциях компоновщика, хотя некоторые из приведённых выше опций компоновщика (подобных -Map или --defsym) нуждаются в пробелах. В этих ситуациях, пробел может быть заменен эквивалентным символом. Например, следующая командная строка может быть использована, чтобы скомпилировать foo.c в исполняемый файл и вывести карту компоновки, которая содержит список перекрестных ссылок, в файл 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

Смотрите описание секции данных для разъяснения, почему необходимо добавить 0x800000 к реальному значению. Заметьте, что стек всё еще остается во внутренней RAM, начиная с символа , который обеспечивается исполняемым кодом инициализации. Это вероятно является хорошей идеей (так как доступ к внутренней RAM быстрее), и даже обязательно для некоторых ранних контроллеров, у которых были аппаратные ошибки, не допускающие использование ими стека во внешней RAM. Заметьте, что динамически распределяемая область памяти для всё ещё может быть выделена после всех переменных в секции данных, при этом конфликтов между стеком и динамически распределяемой памятью не произойдет.

Как правило, чтобы переместить стек из его стандартного расположения вверху внутренней RAM, значение символа может быть изменено в командной строке компоновщика. Так как компоновщик обычно вызывается из препроцессора компилятора, этого можно достигнуть, используя опцию компилятора, подобную следующей:

-Wl,--defsym=__stack=0x8003ff

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

Создание первого проекта

Следующая задача состоит в том, чтобы создать проект на основе AVR микроконтроллера и протестировать схему, компилятор и программатор.

Сначала перейдите в: Файл -> Создать -> Проект (англ. File -> New -> Project) и в открывшемся окне выберите: Исполняемый проект GCC C (англ. GCC C Executable Project), а в текстовом поле Имя (англ. Name) дайте любое название вашему проекту.

Следующее окно, которое должно появиться, — это окно выбора устройства. Из списка выберите Atmega168. Насколько мне известно, это окно не имеет никакого смысла, так как мы все равно передаем имя устройства в AVRDUDE вручную (пока я не могу найти способ заставить Atmel Studio 7 автоматически отправлять имя устройства в AVRDUDE через аргументы).

Результатом должен стать файл main.c, содержащий код нашей программы, который будет запускать AVR. Однако сгенерированный код ничего не делает, поэтому замените все содержимое файла main.c с помощью приведенной ниже программы (обязательно сохраните файл после ввода нового кода).

#define F_CPU 800000UL // Я использую кристалл 8 МГц

#include <avr/io.h>
#include <avr/delay.h>

int main(void){
	DDRD = 0xFF; // Сделать порт D портом выхода

	while(1){
		PORTD = 0xFF;
		_delay_ms(1000);
		PORTD = 0x00;
		_delay_ms(1000);
	}
}

Теперь пришло время скомпилировать код и загрузить его на устройство AVR. Первый шаг — убедиться, что наш проект использует компилятор WINAVR. Щелкните правой кнопкой мыши проект и выберите «Дополнительно» (англ. — Advanced) в окне свойств.

В окне «Дополнительно» убедитесь, что в поле «Набор инструментов» (англ. — Toolchain Flavour) выбран WINAVR.

Сохраните проект и скомпилируйте его, нажав: Build -> Build Solution (или нажав F7). Если все идет по плану, в окне вывода должно появиться следующее сообщение:

Build succeeded.

========== Build: 1 succeeded or up-to-date, 0 failed, 0 skipped ==========

Это означает, что наш проект успешно скомпилирован и готов к передаче на наш чип. Чтобы запрограммировать устройство, убедитесь, что USBASP подключен как к ПК, так и к цепи Atmega, к цепи подано питание и что к микросхеме подключен кристалл (в случае, если микросхема была настроена для использования внешнего кристалла).

Затем, после всего этого, нажмите: Инструменты -> USBASP (англ. Tools -> USBASP), и все будет работать автоматически.

Если все хорошо, светодиод в вашей цепи должен начать мигать. Ниже приведен вывод AVRDUDE в Atmel Studio 7, показывающий, как выглядит успешная программа.

avrdude.exe: warning: cannot set sck period. please check for usbasp firmware update.
avrdude.exe: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.01s

avrdude.exe: Device signature = 0x1e9406
avrdude.exe: NOTE: FLASH memory has been specified, an erase cycle will be performed
             To disable this feature, specify the -D option.
avrdude.exe: erasing chip
avrdude.exe: warning: cannot set sck period. please check for usbasp firmware update.
avrdude.exe: reading input file "0x26"
avrdude.exe: writing lfuse (1 bytes):

Writing | ################################################## | 100% 0.00s

avrdude.exe: 1 bytes of lfuse written
avrdude.exe: verifying lfuse memory against 0x26:
avrdude.exe: load data lfuse data from input file 0x26:
avrdude.exe: input file 0x26 contains 1 bytes
avrdude.exe: reading on-chip lfuse data:

Reading | ################################################## | 100% 0.00s

avrdude.exe: verifying ...
avrdude.exe: 1 bytes of lfuse verified
avrdude.exe: reading input file "c:\users\robinlaptop\Documents\Atmel Studio\7.0\OurFirstAVR\OurFirstAVR\Debug\OurFirstAVR.hex"
avrdude.exe: writing flash (184 bytes):

Writing | ################################################## | 100% 0.11s

avrdude.exe: 184 bytes of flash written
avrdude.exe: verifying flash memory against c:\users\robinlaptop\Documents\Atmel Studio\7.0\OurFirstAVR\OurFirstAVR\Debug\OurFirstAVR.hex:
avrdude.exe: load data flash data from input file c:\users\robinlaptop\Documents\Atmel Studio\7.0\OurFirstAVR\OurFirstAVR\Debug\OurFirstAVR.hex:
avrdude.exe: input file c:\users\robinlaptop\Documents\Atmel Studio\7.0\OurFirstAVR\OurFirstAVR\Debug\OurFirstAVR.hex contains 184 bytes
avrdude.exe: reading on-chip flash data:

Reading | ################################################## | 100% 0.10s

avrdude.exe: verifying ...
avrdude.exe: 184 bytes of flash verified

avrdude.exe: safemode: Fuses OK

avrdude.exe done.  Thank you.

Make и makefiles

Теперь мы можем автоматизировать этот процесс, создав Makefile и поместив туда наши команды. Структура Makefile очень проста, и дополнительную информацию о ней можно найти здесь . Утилита make автоматически считывает файл Makefile в папке, в которой вы ее запускаете. Взгляните на готовый пример:

MCU=attiny13
F_CPU=1200000
CC=avr-gcc
OBJCOPY=avr-objcopy
CFLAGS=-std=c99 -Wall -g -Os -mmcu=${MCU} -DF_CPU=${F_CPU} -I.
TARGET=main
SRCS=main.c

all:
${CC} ${CFLAGS} -o ${TARGET}.bin ${SRCS}
${OBJCOPY} -j .text -j .data -O ihex ${TARGET}.bin ${TARGET}.hex

flash:
avrdude -p ${MCU} -c usbasp -U flash:w:${TARGET}.hex:i -F -P usb

clean:
rm -f *.bin *.hex

Если вы запустите в терминале простую команду make , будет выполнена только метка «all». При запуске (sudo) make flash будет выполнена метка «flash» и так далее.

make

avr-gcc -std=c99 -Wall -g -Os -mmcu=attiny13 -DF_CPU=1200000 -I. -o main.bin main.c
avr-objcopy -j .text -j .data -O ihex main.bin main.hex

make flash

avrdude -p attiny13 -c usbasp -U flash:w:main.hex:i -F -P usb

avrdude: warning: cannot set sck period. please check for usbasp firmware update.
avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e9007
avrdude: NOTE: «flash» memory has been specified, an erase cycle will be performed
To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: warning: cannot set sck period. please check for usbasp firmware update.
avrdude: reading input file «main.hex»
avrdude: writing flash (40 bytes):

Writing | ################################################## | 100% 0.05s

avrdude: 40 bytes of flash written
avrdude: verifying flash memory against main.hex:
avrdude: load data flash data from input file main.hex:
avrdude: input file main.hex contains 40 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.03s

avrdude: verifying …
avrdude: 40 bytes of flash verified

avrdude: safemode: Fuses OK (H:FF, E:FF, L:6A)

avrdude done.  Thank you.

Схема

Построение схемы довольно простое и может быть выполнено с использованием большинства методов построения схем, включая макет, картон, монтажную плату и печатную плату.

Схема в этом проекте показывает использование простой цепи регулятора мощности (с использованием 7805), которую обеспечивает устройство ATMEGA 5В, но оказывается, что программатор USBASP обеспечивает приблизительно 3,3 В. Несмотря на это, лучше обеспечить внешнее питание, чтобы USBASP не потреблял слишком много тока из любого USB-порта.

Программатор USBASP, который я купил, также шел с конвертером, который преобразует 10-контактный разъем в более удобный 6-контактный программный разъем. Тем не менее, header использует двухрядный шаг 2,54 мм, что означает, что он не может быть подключен к макету. Чтобы обойти это, я просто подключил разъем к проводам, которые соединяются с различными пинами на макете.

__________________синтаксис цикла while_____________________________

while(condition){             statement1;     statement2;     statement3;}while – имеет условие выполнения (condition), оно записано в скобках () и тело цикла, оно заключено между фигурными скобками {}. В качестве условия цикла может выступать переменная, константа, выражение или функция,  возвращающая значение. Перед каждым выполнением цикла происходит проверка условия, если условие истинно, цикл выполняется, если условие ложно, цикл не выполняется. Любое ненулевое значение в скобках оператор воспримет как истину, и цикл будет выполняться.            while(1){    //этот цикл будет выполняться бесконечно     statement1;     statement2;     statement3;}

Компиляция и запись кода

Плата разработки Attiny13
Attiny13A, кнопка сброса, две отдельные кнопки, два светодиода, потенциометр, 5В или 3,3 В…

Подробнее

Теперь, когда у вас установлен компилятор, следующий шаг — скомпилировать простой исходный код в файл .BIN, затем сгенерировать файл Intel .HEX и, наконец, записать этот файл .HEX на микросхему AVR с помощью программатора для AVR.

Пример кода

Вот пример содержимого файла main.c. Код ничего не делает, кроме зацикливания в бесконечном цикле, но это для примера.

int
main(void)
{
while (1);
}

Компиляция

Приведенная ниже команда скомпилирует ваш код. Это GCC, поэтому я полагаю, что он вам знаком, и никакой дополнительной информации не требуется. Если вы хотите выполнить компиляцию для другого MCU, вам нужно указать соответствующую опцию -mmcu.

avr-gcc -Wall -g -Os -mmcu=attiny13 -o main.bin main.c

После успешной компиляции вы можете проверить размер памяти программы и данных с помощью этой команды:

avr-size -C main.bin

AVR Memory Usage
—————-
Device: Unknown
Program:      40 bytes
(.text + .data + .bootloader)
Data:          0 bytes
(.data + .bss + .noinit)

Создание .HEX

Большинство программаторов не принимают в качестве входного файла исполняемый файл GNU. Поэтому нам нужно проделать некоторую работу.

Итак, следующий шаг — преобразование информационной формы .BIN в файл .HEX. Утилита GNU, которая делает это, называется avr-objcopy.

avr-objcopy -j .text -j .data -O ihex main.bin main.hex

Программирование

Утилита под названием avrdude может программировать микропроцессоры, используя содержимое файлов .HEX, указанных в командной строке.

С помощью приведенной ниже команды файл main.hex будет записан во флэш-память. Параметр -p attiny13 позволяет avrdude узнать, что мы работаем с микроконтроллером ATtiny13. Другими словами — эта опция определяет устройство.

Полный список поддерживаемых чипов можно найти здесь. Обратите внимание, что также допустимо использовать и полные имена (т. е

t13 равно attiny13).

avrdude -p attiny13 -c usbasp -U flash:w:main.hex:i -F -P usb

И вуаля! Чип запрограммирован.

Как установить WINAVR

Хотя Atmel Studio 7 полезная штука для написания кода, она не самый лучший выбор, когда речь идет о программировании устройств AVR с использованием инструментов с открытым исходным кодом. Поэтому, чтобы сделать жизнь проще на этапе компиляции и/или программирования, мы будем использовать WINAVR, которая также поставляется с AVRDUDE для загрузки нашего кода на устройства Atmega. Чтобы скачать WINAVR для Windows, просто нажмите на эту ссылку и выберите исполняемый exe-файл.

После скачивания запустите установщик и просмотрите все предложенные опции, пока программа не спросит вас про место установки.

Лучшее место для установки WINAVR — это рекомендуемое расположение: . Следующая опция спросит про компоненты и вы должны убедиться, что установлены все галочки (показано ниже).

После того, как кнопка установки нажата, установщик выполнит остальную часть работы, после чего установщик закроется.

_____________________________________________________________________

   Мы хотим, чтобы светодиод моргал с частотой видимой нашему глазу. Это единицы, десятки герц. Допустим, мы выбрали 1 Гц. Мой микроконтроллер работает на частоте 8 МГц, длительность одного такта =1/8000000 Гц = 125 нс. Сигнал частотой 1 Гц имеет период повторения 1 c. Светодиод будет гореть только половину периода — 0,5с. Делим 0,5 с на 125 нс и получаем искомое число тактов – 4000000. Это число укладывается в диапазон типа unsigned long int. Следующая строчка нашей программы – вызов функции:__delay_cycles(4000000);Далее – гасим светодиод и снова вызываем функцию задержки:PORTC = 255;__delay_cycles(4000000);5 шаг алгоритма – вернуться на шаг 2. По сути дела нам нужно повторить кусок программы, зациклить его. Для этих целей в Си существуют три типа циклов: for, while и do. Мы используем while.

________________________________________________________

   Для каждого типа микроконтроллера есть свой заголовочный файл. Для ATMega8535 этот файл называется iom8535.h, для ATMega16 – iom16.h. По идее мы должны в начале каждой программы подключать заголовочный файл того микроконтроллера, который мы используем.  Умные люди немного облегчили нам жизнь и написали заголовочный файл ioavr.h. Препроцессор обрабатывает этот файл и в зависимости от настроек проекта включает в нашу программу нужный заголовочный файл. Итак, следущая строчка программы #include <ioavr.h>    В нашей программе мы будем использовать задержку. Задержку можно реализовать программно и аппаратно. Сейчас нас интересует программная задержка. IAR содержит библиотеку, в которой уже есть готовая функция задержки. Нам нужно подключить к нашей программе эту библиотеку. Как это сделать? Каждая библиотека имеет свой заголовочный файл в котором описано какие фукции она содержит. Этот файл мы и должны включить в программу. Делается это, как вы догадались с помощью директивы #include.#include <intrinsics.h>       Основу любой сишной программы составляют функции, и любая  программа на Си имеет хотя бы одну функцию – main().Вообще-то на примере main() не хотелось бы объяснять синтаксис функций, потому что main() хоть и является функцией, но вызывается не как обычно, а автоматически. С этой функции микроконтроллер начинает выполнение написанной нами программы. Вызовы всех других функций, наших или библиотечных, должны быть записаны в коде. Как вызывается функция, мы увидим дальше.У функции есть заголовок – int main(void) и тело – оно ограниченно фигурными скобками {}. В тело функции  мы и будем добавлять наш код.

Как установить AVR Studio

Устройства AVR программируются с использованием специально модифицированной Visual Studio 2015 под названием AVR Studio 7, которую можно найти на сайте AVR. Первым шагом в программировании устройств AVR является скачивание установщика (небольшого приложения, которое загружает потом необходимые файлы). После скачивания нужно запустить установщик.

Первое, что он вас спросит, будет текст лицензионного соглашения и вопрос про отправку анонимной информации. Я лично рекомендую вам не отправлять анонимные данные по ряду причин (из-за крайней паранойи).

На следующей странице спрашивается какую архитектуру вы хотите установить. Поскольку наш материал охватывает только устройства из диапазона 8-битных микроконтроллеров AVR, то это будет единственная выбранная опция. Однако, если у вас приличная скорость загрузки (у меня всего 4 Мбит/с), тогда выбор всех опций может пригодиться в будущем.

После выбора поддерживаемого устройства на следующей странице будет задан вопрос про расширения — Atmel Software Framework и примеры проектов. Убедитесь, что галочка стоит.

Следующая страница просто проверяет ваш компьютер на наличие потенциальных проблем, таких как отложенный перезапуск (из-за обновления), или если система не сможет запустить IDE. Если все проверено и ОК, жмите «Далее».

Если вы уже установили более раннюю версию AVR IDE, вы можете увидеть следующее окно. Если это так, просто нажмите «Установить».

Теперь нужно подождать пока IDE загрузит все необходимые компоненты и установит их.

После этого вам будет предложено запустить Atmel Studio 7.0. Убедитесь, что стоит галочка перед закрытием окна установки.

Комплектующие

Микроконтроллеры AVR имеют некоторые преимущества по сравнению с другими аналогичными микросхемами, включая более высокую MIPS и более дружественную архитектуру. В этой статье мы узнаем, как использовать AVR IDE, как создать исполняемый проект, построить базовую схему AVR, а затем запрограммировать ее. Для этого нам понадобится набор компонентов, а также некоторое программное обеспечение.

Оборудование:

  • ATMEGA168 DIP IC x 1
  • Кварцевые резонаторы, кристалл (4-20 МГц) x 1
  • 20 пФ конденсатор x 2
  • 680 резистор x 1
  • 5.6K резистор x 1
  • Светодиод LED x 1
  • Источник 5 В (цепь 7805, плавное регулирование и т.д.) x 1
  • Провода

Программное обеспечение:

  • USBASP
  • WINAVR (20100110)
  • Atmel Studio 7

Некоторые опции компоновщика

Хотя это не платформозависимые опции для avr-ld, перечисленные стандартные опции могут быть интересны пользователям AVR.

-lимя
Указывает расположение статической библиотеки, названной libимя.a, и использует её для определения из неё неопределенных символов. Библиотека ищется по пути, который задан в списке стандартных каталогов, которые заданы во время компиляции (например, для Unix-систем это /usr/local/avr/lib), и который можно расширить списком каталогов, заданным опциями -L (которые должны предшествовать опциям -l в командной строке).
-Lпуть
Дополнительное место для поиска статических библиотек, запрашиваемых опциями -l.
--defsym symbol=expr
Определяет использование значения выражения expr вместо глобального символа symbol.
-M
Печать карты компоновки в стандартный выходной поток stdout.
-Map mapfile
Печать карты компоновки в файл распределения mapfile.
--cref
Вывод таблицы перекрёстных ссылок в файл распределения mapfile (в случае передачи опции -Map) или в stdout.
--section-start sectionname=org
Начинает секцию sectionname с абсолютного адреса org.
-Tbss org-Tdata org-Ttext org
Начинает секцию bss, data или org с адреса org.
-T scriptfile
Использует scriptfile как скрипт компоновщика, заменяя стандартный скрипт компоновщика. Стандартные скрипты компоновщика записаны в каталоге, зависящем от системы (например, /usr/local/avr/lib/ldscripts для Unix-систем), и состоят из имени архитектуры AVR (с avr2 по avr5) с добавленным суффиксом .x. Они описывают, как различные секции памяти должны быть связаны между собой.

Резюме

По сути, если предположить, что наша программа находится в main.c , только эти три вещи необходимы для компиляции и записи кода на чип AVR.

  1. $ avr-gcc -Wall -g -Os -mmcu=attiny13 -o main.bin main.c
  2. $ avr-objcopy -j .text -j .data -O ihex main.bin main.hex
  3. $ avrdude -p attiny13 -c usbasp -U flash:w:main.hex:i -F -P usb

Важно подчеркнуть, что мы можем легко автоматизировать весь процесс с помощью Makefiles. Рано или поздно она вам понадобится!

Скачать файлы примера (2,1 KiB, скачано: 168)

Цифровой мультиметр AN8009
Большой ЖК-дисплей с подсветкой, 9999 отсчетов, измерение TrueRMS…

Подробнее

Платформозависимые опции ассемблера

-mmcu=архитектура-mmcu=типМК
avr-as не понимает как avr-gcc вышеупомянутые опции -mmcu=. По умолчанию принимается архитектура avr2, но это может быть изменено использованием соответствующей псевдоинструкцией .arch внутри исходного ассемблерного файла.
-mall-opcodes
Выключает проверку кодов операций для текущего типа МК, и позволяет ассемблировать любые возможные для AVR коды операций.
-mno-skip-bug
Не выдаёт предупреждений при попытке пропуска команд из двух слов с помощью команд . Ранние AVR микроконтроллеры страдали от аппаратной ошибки, из-за которой эти команды не могли быть пропущены должным образом.
-mno-wrap
Для команд , не разрешает целевой адрес для относительного перехода для контроллеров, у которых более 8 кбайт памяти.
--gstabs
Создаёт отладочные символы .stabs для исходных ассемблерных строк. Это включает avr-gdb для отслеживания по исходным ассемблерным строкам. Эту опцию нельзя использовать, когда ассемблируются исходники, которые созданы Си компилятором; эти файлы уже содержат соответствующую построчную информацию из исходных Си файлов.
-a
Включает ассемблерный листинг. Субопции:

  • c пропускает ложные условные операторы;
  • d пропускает отладочные директивы;
  • h включает исходники высокого уровня;
  • l включает скомпонованные блоки;
  • m включает развертывания макросов;
  • n пропускает обработку выражений;
  • s включает символы;
  • =file устанавливает имя файла листинга.

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

Заключение

Начало работы с устройствами AVR может показаться несколько сложным, если вы не используете официальный программатор, который может работать «из коробки» с Atmel Studio 7. Однако в инструментах программирования требуется определить только одну командную строку (тип устройства, биты и т.п.). И все будущие проекты могут использовать один и тот же инструмент/компилятор, который нужно настроить только один раз.

Т.е. следующий проект ATMEGA168, который вы будете делать, сможет использовать тот же компилятор и внешний инструмент, что и в этом проекте и не потребуется никаких дополнительных настроек. Конечно, в более сложных проектах может потребоваться замена бит (англ. fuse), например, но в данном материале я хотел просто помочь вам освоить работу с устройствами AVR.

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Adblock
detector