|
В. Полетаев
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.
|