В. Полетаев
Frequently asked questions ответы на часто задаваемые вопросы по компилятору IAR C для микроконтроллеров AVR фирмы Atmel дает В. Полетаев (vmp@aha.ru)
Компилятор IAR C для микроконтроллеров AVR фирмы Atmel
Существует несколько версий компилятора — 1.40, 1.41, 1.50, но по некоторым причинам наибольшее распространение в России получила версия 1.40c. Версия компилятора смотрится в файле ewa90d.txt — не путать с версией оболочки.
Вопрос: Я установил IAR Embedded Workbench и “патчи” к нему. Что мне ещё нужно?
Ответ: Версия 1.40 поставляется с не совсем корректными .xcl-файлами для линкера. Кроме того, описания регистров микроконтроллеров в нём неполные. Для нормальной работы имеет смысл либо взять комплект .xcl- и h-файлов от более новой версии компилятора, либо с сайта фирмы Atmel (ftp://www.atmel.com/pub/atmel/avr030.zip; ftp://www.atmel.com/pub/atmel/io_def.zip).
Файлы из этих архивов следует переписать в соответствующие каталоги вместо поставлявшихся с компилятором.
При работе в Embedded workshop правильное имя .xcl-файла следует указывать отдельно для каждой target в Project|Options|XLINK|Include|XCL file name, включив Override default.
Вопрос: С чего начать?
Ответ: Лучше всего — полностью прочитать весь help. Это значительно упростит дальнейшее освоение. Печатная документация на компилятор практически слово в слово повторяет help.
Как минимум, следует прочитать разделы Overview и Tutorial в AT90S Windows Workbench Help. Пытаться работать без знаний из этих разделов — бессмысленная трата времени.
Кроме того, рекомендуется посетить на сайте фирмы Atmel раздел http://www.atmel.com/atmel/products/prod201.htm и скачать оттуда ряд документов:
В этом разделе есть ещё ряд документов, посвящённых работе с Си и заслуживающих внимательного ознакомления, из которых особенно отмечу AVR035: Efficient C Coding for AVR (http://www.atmel.com/atmel/acrobat/doc1497.pdf).
Для эффективной работы следует также взять с http://www.atmel.com/atmel/products/prod200.htm последнюю редакцию datasheet и errata на выбранный микроконтроллер и тщательно их изучить, особенно errata.
Вопрос: Отличается ли IAR C от стандартного ANSI C?
Ответ: Да. В IAR C входят различные расширения, связанные с реализацией компилятора для микропроцессора с гарвардской архитектурой (два адресных пространства — для кода и данных) и для более эффективной работы в ограниченных условиях микроконтроллеров. Подробнее смотрите AT90S C Compiler Programming Help, раздел Language extensions.
В исполняющей системе (библиотеке) отсутствуют функции, связанные с вызовами операционной системы (операции с файлами и пр.).
Вопрос: Можно ли разместить таблицы (строки и т. д.) в ПЗУ?
Ответ: Можно. Для этого существует расширение языка — зарезервированное слово flash. Переменная, описанная с применением данного слова, размещается в адресном пространстве кода и доступна только по чтению.
flash char aaa[] = “aaa”;
flash char bbb[] = “bbb”;
flash char ccc[] = “ccc”;
flash char flash *xxx[] = {aaa, bbb, ccc, 0};
Если используется более чем один уровень вложенности, как в вышеприведённом примере (массив указателей на строки), то flash должен стоять для каждого уровня.
Вопрос: Как передать строку char flash * в функцию? Прямое написание строки в параметрах функции не проходит: printf_P(“Строка\n”);
Ответ: Вариант 1.
Описать её отдельно:
{
static flash char str[] = “Строка\n”;
printf_P(str);
}
Рекомендую обратить внимание, что не обязательно выносить описание строки в начало функции. Можно сделать локальный блок и описать в нём переменную, как в примере.
Вариант 2. Пользоваться явным преобразованием типа:
printf_P((char flash *)(int)“Строка\n”);
Можно слегка сократить запись при помощи #define:
#define F (char flash *)(int)
printf_P(F“Строка\n”);
В этом варианте строка будет размещаться в сегменте CSTR. По умолчанию данный сегмент размещается в адресном пространстве данных, поэтому для корректной работы надо исправить XCL-файл. Надо убрать упоминание CSTR из строки:
-Z(DATA)CSTR,CONST=9000-FFFF
(если эта строка присутствует в исходном XCL-файле) и вставить его в строку:
-Z(CODE)INTVEC,RCODE,CDATA0, CDATA1,CCSTR,SWITCH,
FLASH,CODE=0-1FFFF
Вариант 3. Использовать ключ –E.
Этот вариант возможен только при работе с компилятором из командной строки. После указания данного ключа компилятор размещает строковые данные в сегменте CSTR и данные типа const — в CONST, причём считает, что эти сегменты расположены в адресном пространстве кода.
В этом варианте также требуется исправление XCL-файла с переносом CSTR и CONST в строку -Z(CODE).
Кроме того, в этом варианте могут возникнуть проблемы с использованием библиотеки, оттранслированной без ключа –E.
Ну и наконец, в этом варианте компилятор выдаёт предупреждающее сообщение Dangerous configuration, которое можно отключить только вместе со всеми предупреждениями, что неудобно.
На мой взгяд, наиболее приемлимыми являются первый и второй варианты.
Вопрос: Как преобразовать указатель char * в char flash *?
Ответ: Воспользоваться промежуточным int:
char *s;
char flash *p;
p = (char flash *)(int)s;
Вопрос: Где размещаются переменные типа const?
Ответ: Это зависит от установленных опций компилятора. По умолчанию (если не задан ни один из параметров –y или –E) эти переменные размещаются в сегменте CONST, который считается находящимся в адресном пространстве данных. Данный режим делался с расчётом на использование внешней энергонезависимой памяти данных и в большинстве случаев не применяется. Кроме того, в этом режиме компоновщик помещает эти переменные в область кода по тем же адресам, что может вызвать серьёзные проблемы.
Если установлен режим –y –“Writable constants and strings”, то компилятор строит код в полном соотвествии со стандартом ANSI, размещая константы и строки в адресном пространстве данных. Их начальные значения сохраняются в адресном пространстве кода в сегментах CDATA0 или CDATA1 для констант и CCSTR — для строк, а в момент запуска они переписываются в ОЗУ в сегменты IDATA0/IDATA1 и ECSTR, соответственно. Основной недостаток данного режима — непроизводительное использование ОЗУ.
Вариант с указанием ключа –E рассматривался выше. Одновременное использование ключей –y и –E невозможно.
Для написания оптимального варианта программы лучше не пользоваться const, а описывать неизменяемые данные как flash, что приведёт к их явному размещению в памяти программ без лишнего расхода ОЗУ.
Вопрос: Как удобнее работать с битами в регистрах внешних устройств?
Ответ: Для начала описать полезный макрос:
#define Bit(n) (1 << (n))
Для установки бита n в порту p:
p |= Bit(n);
Для сброса бита:
p &= ~Bit(n);
Для проверки бита:
if ((p & Bit(n)) != 0) ...
и так далее.
Полный перечень всех битов доступен на сайте фирмы Atmel в разделе software, файл io_def.zip. Следует поместить эти .h-файлы из этого архива в каталог C:\IAR\EW22DEMO\A90\INC\ вместо существующих.
Вопрос: У меня не работает printf. Что делать для правильного вывода информации в последовательный порт?
Ответ: Во-первых, включить в свою программу отдельную функцию putchar:
int putchar(int c)
{
while ((USR & (1 << UDRE)) == 0);
UDR = c;
return c;
}
Стандартный putchar в библиотеке представляет один оператор RET и не выполняет никакого вывода.
Для доступа к именованным названиям битов регистров следует взять правильный .h-файл из io_def.zip.
Эту функцию следует включать только при компиляции под target=release, иначе под отладчиком может отказаться работать окно Terminal I/O. Простейший способ это сделать — определить для target=debug символ DEBUG (Project|Options|ICCA90|#define, ввести символ) и окружить определение putchar директивами условной компиляции (например, #ifndef DEBUG … #endif).
Во-вторых, следует вставить в начало своей программы процедуру установки скорости обмена последовательного порта. Например, для кварца 5,53 МГц и скорости обмена 115200 бод надо установить:
UBRR = 2;
UCR = 0x18;
В-третьих, обычный printf будет работать только с включенным режимом –y –“Writable constants and strings”.
В-четвёртых, надо правильно выбрать вариант функции printf. Подробности смотрите в AT90S C Compiler Programming Help, Configuration, Input and output.
Стандартная функция printf требует для своей работы минимум 134 байт ОЗУ в стеке. Это страшное расточительство, поэтому есть сокращённые версии printf, обладающие значительно меньшими возможностями форматирования (в частности, не поддерживают задание поля ширины вывода), зато не требующие для работы так много ОЗУ.
В качестве окончательного решения проблемы я бы порекомендовал сделать следующее:
Взять за основу файл C:\IAR\ \EW22DEMO\A90\ETC\intwri.c и произвести в нём следующие изменения:
- добавить строку
#include “pgmspace.h”;
- заменить описание функции на int printf_P (const char flash *format, ...);
- изменить тип массива hex с const на flash: static flash char hex[] = “0123456789ABCDEF”.
После этого не забыть внести нужные изменения в XCL-файл (перенести CSTR в раздел CODE).
Разумеется, надо вставить putchar и инициализацию порта.
После этого забыть про существование printf и пользоваться только printf_P.
Вопрос: Мне не хватает ОЗУ. Что делать?
Ответ: Прочитать AVR035: Efficient C Coding for AVR и внедрить приведённые там рекомендации.
Если кратко — включить оптимизацию по размеру. По возможности, использовать байтовые (char) переменные. Hе перегружать стек локальными переменными большого размера. Стараться делать функции большого (в меру!) размера — так компилятор разложит максимум переменных по регистрам. Об эффективности лучше судить по листингу с включенным режимом insert mnemonics. Передавать в функции лучше не более 2 входных переменных — так они лягут в регистры. Размещать константы в ПЗУ, с ключевым словом flash.
Внимательно изучить используемый .xcl-файл — он приведён в поставке только для примера и кое-где неэффективен. Поставить нижнюю границу всех DATA сегментов (RSTACK, CSTACK, IDATA1, UDATA1, ECSTR) в 60 — так будет достигнуто полное, без дырок, использование ОЗУ. Уточнить размеры аппаратного (RSTACK) и программного (CSTACK) стеков.
Вопрос: У меня не работает порт A. Почему?
Ответ: Порт A используется как шина адреса-данных при работе с внешним ОЗУ. Если оно не используется, то в .xcl-файле следует закомментировать строку -e?RSTACK_IN_EXTERNAL_RAM=? C_STARTUP.
Вопрос: Можно ли создать выходной файл в двоичном виде?
Ответ: Да. Для этого следует указать в качестве выходного формата mpds. Полученный файл с расширением .tsk и будет образом ПЗУ.
Вопрос: Как заменить библиотечный модуль на свой?
Ответ: Проще всего поместить исходный файл с ним в свой рабочий каталог проекта и подключить его к файлу проекта. Дальше оболочка сама разберётся с его типом (.c или .s90) и позаботится о его пристыковке раньше библиотечного.
Вопрос: Как лучше отлаживать программу?
Ответ: Если нужно отладить алгоритм, не зависимый от работы периферии, можно воспользоваться C-SPY. Преимущество — отладка на уровне исходного текста (но можно посмотреть и ассемблерный текст), недостаток — периферия практически отсутствует.
Если нужна работа со стандартной периферией, можно воспользоваться Atmel AVR studio 3.0, которая достаточно точно эмулирует поведение кристаллов. Для передачи в неё файла следует указать xlink’у тип выходного формата debug. Если в окне исходного текста в Astudio символы искажены, то следует установить подходящий моноширинный фонт (например, terminal для ДОС-кодировки русских букв или Courier для Windows) в меню Edit|Fonts…
ВHИМАHИЕ! IAR адресует память программ побайтно, в то время как Atmel — пословно. Поэтому, если в map-файле от компоновщика подпрограмма имеет адрес 1234h, то в astudio надо указывать адрес 1234h/2=091Ah.
Вопрос: EWA90 работает только под Windows?
Ответ: Оболочка — да. Однако есть command-line версии компилятора, ассемблера и компоновщика, которые прекрасно работают под MS-DOS, используя встроенный DOS Extender от Phar Lap Software, Inc.
Основная сложность при работе с ними — огромное количество ключей. Рекомендую для начала поработать в виндовой оболочке, а затем взять список ключей из шапки листинга и поместить его в make-файл.
Вопрос: Периодически при компиляции совершенно правильного файла выдаётся системная ошибка. Что делать?
Ответ: Повторить компиляцию. Это какая-то ошибка в компиляторе, которая иногда возникает.
Вопрос: Что ещё почитать об AVR, кому задать вопрос?
Ответ: На российском сайте фирмы Atmel есть подборка практических рекомендаций: http://www.atmel.ru/AVR/AVR.htm и http://www.atmel.ru/Spec/Spec.htm.
Ответы на вопросы по AVR, задаваемые посетителями сайта ATMEL, можно найти на http://www.atmel.ru/FAQ/FAQ.htm.
Можно задать вопросы российским представителям Atmel — фирме ЭФО через конференцию Atmel на сайте http://www.efo.ru.
Большое число специалистов по AVR регулярно общается и в конференции по микроконтроллерам на сайте Телесистем — http://www.telesys.ru.
|