Добрый день всем,
Пять рабочих дней занимался переводом проекта с CV на IAR, далее привожу подробный отчет, на что стоит обратить внимание. Может кому пригодится. Всё по горячим следам, пока не забыл.
Имеем: проект на CV2.03.9, чип ATmega64A. Еще бутлоадер на том же CV, размер 8192 байт.
Цель: перевести проект на IAR5.30 с минимальным изменением кода.
Причины: а) нехватка памяти flash для развития проекта, б) потребность использовать С++ и float64.
Бутлоадер переводить не будем, т.к. нет необходимости.
Использую EWAVR_CompilerReference.pdf, отличная документация.
1. Создал пустой проект в IAR, указал чип, Memory model = small, Library = DLIB, DSTACK = 512 байт, CSTACK = 128 уровней (256 байт).
2. Опции компилятора: Extra options: добавил command line options:
Код
--string_literals_in_flash
--root_variables
Первая - чтобы строки размещались во flash.
Вторая - чтобы все статические переменные в SRAM и особенно EEPROM были размещены в памяти, даже если они не используются.
3. Опции линкера: Extra options: добавил command line options:
Код
-Ointel-standard,(CODE)=.hex
-Ointel-standard,(XDATA)=.eep
Эти команды нужны для формирования привычных файлов HEX и EEP, как в CodeVision и AVRStudio.
Остальные настройки проекта - по вкусу.
4. Где нужно - инклудятся <ioavr.h> и <intrinsics.h>.
5. Переделываются все прерывания на следующий шаблон:
Код
#pragma vector = TIMER0_COMP_vect
__interrupt void TIMER0_COMP_isr(void) {
//...
}
6. Все переменные bit заменил на bool.
7. Все объявления указателей на строку во flash заменил на такого типа:
Код
const unsigned char __flash *ResetSourceText;
Во все объявления переменных в EEPROM добавил __eeprom, и для констант во flash добавил __flash.
8. Разрешения и запрещения прерываний заменил на __enable_interrupt() и __disable_interrupt(), сбросы сторожевого таймера на __watchdog_reset().
9. Все бинарные константы типа 0b01100011 заменил на BINARY(01100011). Макрос взял
здесь.
10. Все ассемблерные вставки заменил на asm("..."). Перенос строки внутри вставки был '\', теперь '\n'. Пример:
Код
asm("cli \n jmp 0");
11. Функция sprintf() в IAR не поддерживает форматную строку из flash. Для этого инклудим <pgmspace.h> и используем функцию sprintf_P(). То же с функцией strcpyf() -> strcpy_P().
12. Функция sprintf_P() не поддерживает спецификатор '%p' для строк из flash. Модифицировал библиотечный файл frmwri_p.c. Подробнее см.
здесь.
13. Где-то использовалась функция toint() из библиотеки CodeVision. Заменил на:
Код
//interprets c as a hexadecimal digit and returns an usigned char from 0 to 15.
inline unsigned char toint(char c) {
if ((c>='0')&&(c<='9')) return (c-'0');
else
if ((c>='a')&&(c<='f')) return (c-'a')+10;
else
if ((c>='A')&&(c<='F')) return (c-'A')+10;
else return 0;
}
14. Использовал библиотеку софтварной реализации I2C из CodeVision. Поискал готовую для IAR, прикрутил avrlib, не работает, запустить не удалось. Написал свою библиотеку под замену вызовов i2c_start(), i2c_stop(), i2c_write(), i2c_read(), отладил, работает.
15. Проверяю в работе. Периодически сбрасывается по WDT. Долго копался, выяснил, что CV при доступе к переменным EEPROM на чтение и на запись запрещает прерывания, а IAR запрещает только на запись. Нашел решение
здесь. Сравнил eeprom.s90 по ссылке и тот, который есть в IAR. Изменения заключаются в том, что при чтении и записи прерывания запрещаются, а затем восстанавливаются, можно смело использовать и в прерываниях, и в основном потоке. Добавил измененный файл в проект, далее выполнил действия по списку - см. EWAVR_CompilerReference.pdf, Overriding library modules using IAR Embedded Workbench. Еще для компиляции понадобилось скопировать в папку проекта файл macros.m90.
16. При тестировании с бутлоадером обнаружил, что в проекте бутлоадера CodeVision сам переключает таблицу прерываний на начало бутлоадера. А в проекте application - на начало flash. IAR такого не делает. Поэтому при выходе из бутлоадера мы оказались в application, но с таблицей прерываний в области бутлоадера. Короче, это решилось добавлением переключения таблицы прерываний на начало flash перед первым разрешением прерываний:
Код
MCUCR = 1;
MCUCR = 0;
__enable_interrupt();
17. Еще обнаружил, что переход на бутлоадер jmp 0x7000 уходит куда-то не туда. Выяснилось, что ассемблер у IAR отличается от атмеловского и в jmp принимает адрес в байтах, а не в словах. То есть надо задавать удвоенный адрес. Итог: для перехода по адресу 0x7000 выполняем код:
Код
asm("cli \n jmp 0xE000");
Вроде бы пока всё, если еще что-то вылезет - допишу.
Приглашаю всех, у кого есть опыт переноса проекта с CodeVision на IAR, описывать симптомы проблемы и решение здесь.
Сообщение отредактировал Konstantin Ilichev - Sep 3 2011, 07:26