Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: bootloader в IARe 3,10
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > IAR
Страницы: 1, 2, 3
arttab
Необходимо иметь возможность обновлять микрокод мк через последовательный интерфейс. Для экономии места в мк (МЕГА8) хочу сделать так: функции отвечающие за протокол связи должны находиться в области загрузчика как и вектора прерываний.
За размещение векторов в области загрузчика отвечает fuse. Это понятно. За размер загрузчика др. fusы.
Как указать IARу новое место расположения векторов?
Было так:
#pragma vector=USART_TXC_vect
__interrupt void my_USART_TXC_vect(void)
{ ....
Должно быть так:
#pragma vector=0xС1A
__interrupt void my_interrupt_handler(void)
{....
или как то еще можно задать?

Далее. Надо указать место размещения некоторых функций в области загрузчика.
#pragma location="MYSEGMENT"
void f() @ "MYSEGMENT";
void g() @ "MYSEGMENT"
{
}
Так? MYSEGMENT=FLASH_END-BOOT_LOADER_SIZE , Где BOOT_LOADER_SIZE размер загрезчика в словах?

И как на Си будут выглядеть команды стирания страниц и загрузки буфера?
Faradey
посмотрите в примере от Atmel. Там не совсем то что вы хотите, но зато показано как в ИАР писать из бута в память кода.
arttab
Это приложение к ан109. уже взял, уже ковыряю.... Куча вопросов по С++. Во строеном в IAR хелпе мало и фигово описано.
Вопрос к тем кто делал в одном проекте с прогой и бутлоадер:
Для последующего "срастания" обновления с функциями лежащими в бутлоадере, Вы использовали при вызове функций указатели на них? А указатели приравнивали к адресам получившиеся в бутлоадере.
arttab
Что означает __C_task void loader(void)?
Я только понял что это влияет на модель памяти и размещение используемых в функции переменных

Забыл зарегистрироваться. От гостя можно удалить
arttab
Если я правильно понял, то:
_C - указывает что нужно сгенерить сегмент. Начальный адрес указывается где-то далее;
_task - объявляет функцию как не использующию стек. А зачем это и для чего?

Адреса прерываний нужно указывать самому (они будут в загрузчике).
напрмер так?
#pragma vector=0xC1A
__interrupt void my_interrupt_handler(void)
{
asm("NOP");
}
arttab
Еще вопрос по адресам прерываний:
В табл 18 и 19 ан даны адреса.
В табл 19 Reset adres 0x0000 Interrupt vector stsrt adres 0x0001. И это смещение на 1 и при переносе векторов в область загрузчика.
Почему смещение на 1?
IgorKossak
Цитата(arttab @ Jul 6 2006, 07:11) *
Если я правильно понял, то:
_C - указывает что нужно сгенерить сегмент. Начальный адрес указывается где-то далее;
_task - объявляет функцию как не использующию стек. А зачем это и для чего?

Вы не правильно поняли.
_C_task это то же что и __task - указание компилятору не сохранять регистры в прологе функции и не восстанавливать в эпилоге.
Применяется в основном для тех функций, из которых не ожидается выходить, т. е. main или различные функции процессов при применении RTOS.
arttab
Спасибо! Хоть один не отсылает к докам по IARу. В них не все понятно.
Если я правильно понял, то в примерах bootloaderов это фича для красоты.
А по адресам прерываний на Мегу8 ошибка столо быть: начинаются они или с 0х0000 или с начала секции загрузчика. В последнем случае адреса надо самому указать векторов.
А как объяснить IARу что main находиться в секции бутлоадера и в вектор прерывания по ресету в бутлоадере лег правильный адрем main?
arttab
Цитата(Faradey @ Jul 5 2006, 22:18) *
посмотрите в примере от Atmel. Там не совсем то что вы хотите, но зато показано как в ИАР писать из бута в память кода.


Посмотрел Modified_for_Butterfly (другой загружится в IAR не захотел. его смотрел редактором), попробовал скомпилировать. Ошибка: нужно -v3. Ставлю в проекте -v3 ->
Fatal Error[Pe035]: #error directive: This file should not have RAMPZ enabled, use --cpu or --64k_flash

У Вас скомпилировалась?
IgorKossak
Цитата(arttab @ Jul 6 2006, 11:22) *
Если я правильно понял, то в примерах bootloaderов это фича для красоты.

Ну не столько для красоты сколько для экономии памяти кода (у 8-й меги её не так уж много) да ещё из предположения, что функция main не предполагает выхода, а прыжок на 0-й адрес основной программы предполагает переинициализацию (C_Startup) оперативной памяти, периферии и указателей стеков заново.
Цитата(arttab @ Jul 6 2006, 11:22) *
А по адресам прерываний на Мегу8 ошибка столо быть: начинаются они или с 0х0000 или с начала секции загрузчика. В последнем случае адреса надо самому указать векторов.
А как объяснить IARу что main находиться в секции бутлоадера и в вектор прерывания по ресету в бутлоадере лег правильный адрем main?

Не знаю как изощриться в данной ситуации, но я делал немного по другому.
Делал два независимых проекта: приложение и бутлоадер.
Программа всегда стартовала на бутлоадер, без прерываний, только поллинг флагов ЮАРТа (хватало и этого вплоть до скорости 115200). Если не надо было грузить программу (опрос состояния пина), то делался прыжок по адресу 0x0000 к приложению. В этом случае был небольшой оверхед по коду (процедуры чтения/записи байта в порт), но для меги128 это не существенно.
Просто и сердито, и никакой головной боли, и проекты могут не зависеть один от другого, особенно если применяются раздельные контрольные суммы для приложения и бутлоадера.
Может можно и совместно использовать некоторые функции, но это как по мне слегка вяжет руки.
arttab
Ограниченость памяти меги8 и наталкивает на совместное использование некоторых функций.
Кстати, добавил к main __C_task и перекомпил - код меньше не стал. Видно, он сам сообразил.
Вопрос о переносе векторов в загрузщик:
Я устанавливаю fuse BOOTRST=0. Значит после сброса переход будет на BOOTADRES. Тогда пишу

#pragma vector=LOADER
__interrupt void my_interrupt_RESET(void)
{
main();
}
и прочие нужные вектора.
А функции входящие в загрузщик типа так:
void main(void) @ "LOADER";

ругается
Fatal Error[e72]: Segment LOADER must be defined in a segment definition option (-Z, -b or -P)

#define LOADER 0xC00
#pragma location = "LOADER"

как надо подправить cfgm8.xcl что бы было верно?
arttab
Есть вообще возможность разместить 2 таблици векторов прерываний?
Если нет, то прописать нодо
-Z(CODE)INTVEC=(FLASH_SIZE-BOOT_SIZE)-(FLASH_SIZE-BOOT_SIZE+IVT_SIZE-1)

и все? Он сам их правильно расположит? Или как я писал раньше - типа:
Цитата
#pragma vector=LOADER
__interrupt void my_interrupt_RESET(void)
{
main();
}
Old1
Цитата(arttab @ Jul 7 2006, 05:32) *
Ограниченость памяти меги8 и наталкивает на совместное использование некоторых функций.
Кстати, добавил к main __C_task и перекомпил - код меньше не стал. Видно, он сам сообразил.
Вопрос о переносе векторов в загрузщик:
Я устанавливаю fuse BOOTRST=0. Значит после сброса переход будет на BOOTADRES. Тогда пишу

#pragma vector=LOADER
__interrupt void my_interrupt_RESET(void)
{
main();
}
и прочие нужные вектора.
А функции входящие в загрузщик типа так:
void main(void) @ "LOADER";

ругается
Fatal Error[e72]: Segment LOADER must be defined in a segment definition option (-Z, -b or -P)

#define LOADER 0xC00
#pragma location = "LOADER"

как надо подправить cfgm8.xcl что бы было верно?

В настройках проекта, в разделе linker, в закладке extra options вставте строку, например
Цитата
-Z(CODE)LOADER=1C00-1CFF
Сергей Борщ
Цитата(arttab @ Jul 7 2006, 05:32) *
Вопрос о переносе векторов в загрузщик:
Я устанавливаю fuse BOOTRST=0. Значит после сброса переход будет на BOOTADRES. Тогда пишу

#pragma vector=LOADER
__interrupt void my_interrupt_RESET(void)
{
main();
}

Ужас :-)
1) Все же присоединюсь к Игорю и порекомендую два отдельных проекта.
2) фуз BOOTRST дает только переход по сбросу на BOOTADDRESS. Остальные вектора не трогаются. Остальные вектора переназначаются на загрузчик битом IVSEL. Поэтому можно иметь две таблицы векторов (одну для режима загрузчика вторую для боевого). Только прописывать одну из них надо будет на асме.
3) #pragma vector используется точно так же как в обычной программе. вектор в данном случае означает смещение относительно начала сегмента INTVEC. Чтобы таблица векторов попала в BOOT-область надо в .xcl испавить -Z (CODE) INTVEC = 0-26 на -Z(CODE) INTVEC = 1800-1826 (пишу по памяти, насчет 26 мог ошибиться).
Цитата
А функции входящие в загрузщик типа так:
void main(void) @ "LOADER";

ругается
Fatal Error[e72]: Segment LOADER must be defined in a segment definition option (-Z, -b or -P)

#define LOADER 0xC00
#pragma location = "LOADER"

Мимо. перед использованием @ вставить #pragma segment = "LOADER" Только учти, что до main вызывается c_startup, которая живет в библиотеке и попадет в сегмент CODE, а уже из c_startup вызывается main. Тебе придется подключить исходник c_startup к своему проекту и исправить в нем RSEG CODE на RSEG LOADER. Исходник лежит в папке IAR\avr\src\lib
Цитата
как надо подправить cfgm8.xcl что бы было верно?

Сначала признайся - будешь делать один проект или два? Будешь использовать одну таблицу векторов или две?
IgorKossak
arttab, Вы взяли для модифицирования не тот конфигурационный файл.
Чтобы было намного гибче и предсказуемее, сделайте следующее:
1. lnkm8s.xcl из папки \avr\config это то что нужно, скопируйте этот файл в папку проекта
2. в General Options снимите галочку в поле Configure system using dialogs...
3. в опциях XLINK/Include в поле XCL file name укажите путь к Вашему файлу xcl.

Что касается двух таблиц прерываний, то это скорее всего невозможно сделать автоматически. В этой среде поддерживается идеология: один проект - одно распределение памяти.
В таком случае более универсальным будет подход, о котором я уже говорил, сделать два проекта в одном рабочем пространстве.
arttab
Спасибо всем. разбираюсь...
А что значит:
Цитата
сделать два проекта в одном рабочем пространстве
? Я понял что в одном проекте есть и bootloader и обновляемая прога. Или Вы имели ввиду адресное пространство мк?
для линкера и экстра опций нужно указывать в байтах или в словах?
IgorKossak
Цитата(arttab @ Jul 7 2006, 11:00) *
Спасибо всем. разбираюсь...
А что значит:
Цитата
сделать два проекта в одном рабочем пространстве
? Я понял что в одном проекте есть и bootloader и обновляемая прога. Или Вы имели ввиду адресное пространство мк?

Под рабочим пространством имеется в виду именно сущность среды проектирования, называемая workspace, в которой создаются включаемые в неё подсущности, называемые project (меню Project/Add existing project... или Create new project...).
Причём, все проекты одного рабочего пространства можно собирать групповым способом (Project/Batch build), что иногда весьма удобно.
Цитата(arttab @ Jul 7 2006, 11:00) *
для линкера и экстра опций нужно указывать в байтах или в словах?

В байтах, т. к. линкер универсальный на всю поддерживаемую IAR гамму МК.
arttab
Сергей Борщ,
в указаном Вами файле
RSEG LOADER:CODE:NOROOT(1)
менять так:
RSEG LOADER:CODE:NOROOT(1) ?

Попробую сделать отдельный проект для загрузчика
Сергей Борщ
Цитата(arttab @ Jul 7 2006, 11:27) *
Сергей Борщ,
в указаном Вами файле
RSEG LOADER:CODE:NOROOT(1)
менять так:
RSEG LOADER:CODE:NOROOT(1) ?

Да, именно это.
Цитата(arttab @ Jul 7 2006, 11:27) *
Попробую сделать отдельный проект для загрузчика

Тогда оставьте c_startup как есть (точнее отключите от проекта чтобы брался библиотечный) и просто в .xcl измените:
Код
-Z(CODE)INTVEC=1800-1825 /* 19 Interrupt vectors * 2 bytes each */

/* Fill unused interrupt vector's with RETI */
-H1895 -h(CODE)1800-1825

-Z(CODE)TINY_F=1826-18FF
-Z(CODE)NEAR_F,SWITCH,INITTAB,DIFUNCT=1826-1FFF
-Z(CODE)CODE=1826-1FFF
-Z(CODE)TINY_ID,NEAR_ID=1826-1FFF
-Z(CODE)CHECKSUM#1FFF

Цитата(IgorKossak @ Jul 7 2006, 10:32) *
3. в опциях XLINK/Include в поле XCL file name укажите путь к Вашему файлу xcl.

Причем лучше в форме
Код
$PROJ_DIR$\mynew.xcl
Тогда при переносе проекта в другую папку не придется переписывать путь заново.
arttab
Начал делать отдельно Bootloader.
В проекте определил сегмент и внес в неё фу-ии:
#pragma segment = "LOADER"
void main(void) @ "LOADER";
void Init_USART(void) @ "LOADER";

В main переместил таб. векторов:
MCUCR = (1<<IVCE);
MCUCR = (1<<IVSEL); //move interruptvectors to the Boot sector

в XLINK/Extra Options/ прописал -Z(CODE)LOADER=1C26-1FFF
в Genetal использовать XCL не по умолчанию
в XLINK/Include прописал какой файл использовать $PROJ_DIR$\my_lnkm8s.xcl
в файле my_lnkm8s.xcl сделал так:
/*-Z(CODE)INTVEC=0-25 19 Interrupt vectors * 2 bytes each */
-Z(CODE)INTVEC=1C00-1C25


При компиляции появляется код с адресов 1С00 (вектора и прога) и 0000-009E. ???!!!!
IgorKossak
Цитата(arttab @ Jul 9 2006, 08:46) *
Начал делать отдельно Bootloader.
В проекте определил сегмент и внес в неё фу-ии:
#pragma segment = "LOADER"
void main(void) @ "LOADER";
void Init_USART(void) @ "LOADER";

В main переместил таб. векторов:
MCUCR = (1<<IVCE);
MCUCR = (1<<IVSEL); //move interruptvectors to the Boot sector

в XLINK/Extra Options/ прописал -Z(CODE)LOADER=1C26-1FFF
в Genetal использовать XCL не по умолчанию
в XLINK/Include прописал какой файл использовать $PROJ_DIR$\my_lnkm8s.xcl
в файле my_lnkm8s.xcl сделал так:
/*-Z(CODE)INTVEC=0-25 19 Interrupt vectors * 2 bytes each */
-Z(CODE)INTVEC=1C00-1C25


При компиляции появляется код с адресов 1С00 (вектора и прога) и 0000-009E. ???!!!!

Если проект отдельный, нет нужды создавать сегмент LOADER.
Достаточно переопределить диапазоны адресов у существующих сегментов.
Кроме того, компилятор (а не линкер) по умолчанию использует зарезервированные имена сегментов, в частности INTVEC для векторов прерываний, NEAR_ID для инициализаторов и т. д.
И я не знаю как эти сегменты по умолчанию, используемые неявно, переключить на новые имена.
arttab
Спасибо за подсказку. В my_lnkm8s.xcl переправил так:
/* -Z(CODE)NEAR_F,SWITCH,INITTAB,DIFUNCT=26-1FFF */
-Z(CODE)NEAR_F,SWITCH,INITTAB,DIFUNCT=1C26-1FFF
/* -Z(CODE)CODE=26-1FFF */
-Z(CODE)CODE=1C26-1FFF
/* -Z(CODE)TINY_ID,NEAR_ID,CHECKSUM=26-1FFF */
-Z(CODE)TINY_ID,NEAR_ID,CHECKSUM=1C26-1FFF

Код в начале остался только с 00 по 25.

А как сделать 2 проекта в одном пространстве? Что получиться на выходе? 2 Hex файла? И что это дает?
И еще вопрос по операциям стирания и записи в буфер....
Это все делается через регистры РОН. К ним можно получить доступ из Си? no_init unsigned char @ 0x00 RR0 Или нужно делать асм. вставки? Не будет ли конфликта с компилятором?
Ы.З. Похоже из моих попыток получиться пособие для других как сделать bootloader smile.gif
Сергей Борщ
Цитата(arttab @ Jul 10 2006, 17:15) *
Код в начале остался только с 00 по 25.

Обрати внимание на строчку .xcl:
-H1895 -h(CODE)00-25
Цитата(arttab @ Jul 10 2006, 17:15) *
А как сделать 2 проекта в одном пространстве? Что получиться на выходе? 2 Hex файла? И что это дает?
общие исходные файлы?
Цитата
И еще вопрос по операциям стирания и записи в буфер....
Это все делается через регистры РОН. К ним можно получить доступ из Си?
Не совсем понял о каком буфере идет речь, но если о команде SPM, то обрати внимание на функции и макросы из intrinsics.h:
Код
#define _SPM_FILLTEMP(Addr,Data)  \
  __AddrToZWordToR1R0ByteToSPMCR_SPM((void __flash*)(Addr), (Data), 0x01)

#define _SPM_PAGEWRITE(Addr) \
  __AddrToZByteToSPMCR_SPM((void __flash*)(Addr), (0x05))

Цитата
Ы.З. Похоже из моих попыток получиться пособие для других как сделать bootloader smile.gif

Ну если описать толково, то beer_warrior не должен отказаться включить в FAQ :-)
arttab
Цитата
Обрати внимание на строчку .xcl:
-H1895 -h(CODE)00-25

Увидел. Исправил -H1895 -h(CODE)1C0-1C25
Кстати, в примерах видел выражения типа FLASH_SIZE-BOOT_SIZE, но у меня так сделать не вышло. Нужно какуюто библиотеку прицепить?
Цитата
Не совсем понял о каком буфере идет речь, но если о команде SPM, то обрати внимание на функции и макросы из intrinsics.h:

Оно. Я не ясно выразился, но Вы правильно поняли. Поразбараюсь с intrinsics.h
Спасибо, буду дальше разбираться
arttab
Сергей Борщ? А где лежит файл intrinsics.h? не нашел в каталоге IAR. Или это в старшей версии есть?
Сергей Борщ
Цитата(arttab @ Jul 11 2006, 06:03) *
Сергей Борщ? А где лежит файл intrinsics.h? не нашел в каталоге IAR. Или это в старшей версии есть?
Не знаю что считать старшей версией, у меня в 4.10B лежит в каталоге IAR\AVR\INC
arttab
Цитата
Не знаю что считать старшей версией

Имел в виду цифры версии. В 4.10 есть, а в моей 3.10 нет. файл взял у др. человека.
Как я понял, в этом файле описываются функции. Если я подключю к своему проекту, не будет ли конфликта версий? Или взять из файла только нужное:
__intrinsic void __DataToR0ByteToSPMCR_SPM(unsigned char data, unsigned char byte);

__DataToR0ByteToSPMCR_SPM
{
MOV R0,data
OUT SPMCR,byte
SPM
}
Или надо переходить на версию 4.10 и старше (>4.10)
Сергей Борщ
Цитата(arttab @ Jul 11 2006, 12:36) *
Цитата
Не знаю что считать старшей версией

Имел в виду цифры версии. В 4.10 есть, а в моей 3.10 нет.
Да, извиняюсь. Я поискал упоминание версии в постах а в тему и не посмотрел :-)
Цитата
файл взял у др. человека.
Как я понял, в этом файле описываются функции. Если я подключю к своему проекту, не будет ли конфликта версий?
В нем описываются прототипы функций. Сами тела __intrinsic- функций знает компилятор. Это позволяет ему встраивать тела функций в код очень эффективно.
Цитата
Или взять из файла только нужное:
__intrinsic void __DataToR0ByteToSPMCR_SPM(unsigned char data, unsigned char byte);
__DataToR0ByteToSPMCR_SPM
{
MOV R0,data
OUT SPMCR,byte
SPM
}
Боюсь такой вариант не пройдет. Особенно последняя смесь асма и С. Если нет возможности перейти на более свежую версию - то имеет смысл эти функции написать самому на асме (как в приложенных файлах от апликашки AES loader). Однако такой вариант будет менее эффективным ибо компилятор не сможет встроить такие функции.
Цитата
Или надо переходить на версию 4.10 и старше (>4.10)
Это наиболее здравое решение. Снизу вверх проекты конвертятся легко.
arttab
Уф, переполз на 4.12А. с трудом.
intrinsics.h нужно подключить к проекту или она автоматом как только сделаю вызов ее функций?
выражения типа FLASH_SIZE-BOOT_SIZE работают в этой версии?
Пока поразбираюсь SPM функциями intrinsics.h
arttab
Сергей Борщ, не моглибы Вы прокоментировать мои изыскания:
/*
__DataToR0ByteToSPMCR_SPM, pseudo code.
MOV R0,data
OUT SPMCR,byte
SPM
*/
__intrinsic void __DataToR0ByteToSPMCR_SPM(unsigned char data,
unsigned char byte);
Какой смысл этой команды? Нужно по 2 байта в буфер отправлять,
а по одному R0 не используется.
//-------------------------------------------
/*
__AddrToZByteToSPMCR_SPM, pseudo code.
MOVW R31:R30,addr
OUT SPMCR,byte
SPM
*/
__intrinsic void __AddrToZByteToSPMCR_SPM(void __flash* addr,
unsigned char byte);

Передается адрес и выполняется возможная команда ( команда - byte):
стирание страници, запись страници
//------------------------------------------------
/*
__AddrToZWordToR1R0ByteToSPMCR_SPM, pseudo code.
MOVW R31:R30,addr
MOVW R1:R0,word
OUT SPMCR,byte
SPM
*/
__intrinsic void __AddrToZWordToR1R0ByteToSPMCR_SPM(void __flash* addr,
unsigned short word,
unsigned char byte);
запись данных word (2 Б) в буфер по адресу addr.
значение byte фиксировано (1<<PGWRT)&(1<<SPMEN)
//----------------------------------------------
/*
__AddrToZByteToSPMCR_LPM, pseudo code.
MOVW R31:R30,addr
OUT SPMCR,byte
LPM
*/
__intrinsic unsigned char __AddrToZByteToSPMCR_LPM(void __flash* addr,
unsigned char byte);
Ошибка или это что то специфическое?
//---------------------------------------
Что то не понял я с этой библиотекой
И как Вы управляли самопрограммированием (какие функции использовали для стирания, записи, ожидания готовности...).
Сергей Борщ
Цитата(arttab @ Jul 13 2006, 10:33) *
Сергей Борщ, не моглибы Вы прокоментировать мои изыскания:
Постараюсь по мере возможностей. Сначала сделаю отступление: эти функции я в своей работе пока не использую, поскольку в части проектов у меня загрузчик написан на асме а в части я использую AES Loader из аппликашки Атмела. С этими функциями я баловался еще в версии 2.28 (сейчас нашел тот исходник, там судя по исходнику их прототипы были описаны в pgmspace.h. Вот тот исходник:
Код
#include    <iom8.h>
#include    <inavr.h>
#include    <pgmspace.h>

void ErasePage (unsigned char page);

const __root __flash unsigned char TestFill[64] @ (0x10 << 6) = {1,2,3,4,5};

void main (void) {
DDRC = (1<<2)|(1<<3);
PORTC = 0;
ErasePage(0x10);
for(;;)
  PORTC ^= (1<<2);

}

void ErasePage(unsigned char page) @ "BLS" {
_SPM_ERASE((unsigned int)page << 6);
while(SPMCR & (1<<SPMEN)) PORTC |= (1<<3);
__DataToR0ByteToSPMCR_SPM(0, (1<<RWWSRE)|(1<<SPMEN));
}
arttab
Спасибо. Просто я не понял как ими воспользоваться. Т.е. какие функции вызывать с какими параметрами. попробую еще в help поискать на IAR
arttab
Люди, подскажите - есть ли в IAR функции для самопрограмирования? Очистить буфер, занести слово в буфер, записать буфер, биты защиты выстывить....
IgorKossak
Цитата(arttab @ Jul 14 2006, 09:57) *
Люди, подскажите - есть ли в IAR функции для самопрограмирования? Очистить буфер, занести слово в буфер, записать буфер, биты защиты выстывить....

Вот выдержка из проекта AVR109 - Self-programming с сайта Atmel:
Код
/*****************************************************************************
*
* Atmel Corporation
*
* File              : flash.h
* Compiler          : IAR C 3.10C Kickstart
* Revision          : $Revision: 1.1 $
* Date              : $Date: 2005/07/18 07:39:01 $
* Updated by        : $Author: Atmel $
*
* Support mail      : avr@atmel.com
*
* Target platform   : All AVRs with bootloader support
*
* AppNote           : AVR109 - Self-programming
*
* Description       : Flash operations for AVR109 Self-programming
****************************************************************************/


#define _GET_LOCK_BITS() __AddrToZByteToSPMCR_LPM( (void __flash *) 0x0001, 0x09 )
#define _GET_LOW_FUSES() __AddrToZByteToSPMCR_LPM( (void __flash *) 0x0000, 0x09 )
#define _GET_HIGH_FUSES() __AddrToZByteToSPMCR_LPM( (void __flash *) 0x0003, 0x09 )
#define _GET_EXTENDED_FUSES() __AddrToZByteToSPMCR_LPM( (void __flash *) 0x0002, 0x09 )
#define _SET_LOCK_BITS(data) __DataToR0ByteToSPMCR_SPM( data, 0x09 )
#define _ENABLE_RWW_SECTION() __DataToR0ByteToSPMCR_SPM( 0x00, 0x11 )

#define _WAIT_FOR_SPM() while( SPMCR_REG & (1<<SPMEN) );

#ifndef LARGE_MEMORY
  #define _LOAD_PROGRAM_MEMORY(addr) __load_program_memory( (const unsigned char __flash *) (addr) )
  #define _FILL_TEMP_WORD(addr,data) __AddrToZWordToR1R0ByteToSPMCR_SPM( (void __flash *) (addr), data, 0x01 )
  #define _PAGE_ERASE(addr) __AddrToZByteToSPMCR_SPM( (void __flash *) (addr), 0x03 )
  #define _PAGE_WRITE(addr) __AddrToZByteToSPMCR_SPM( (void __flash *) (addr), 0x05 )
#else
  #define _LOAD_PROGRAM_MEMORY(addr) __extended_load_program_memory( (const unsigned char __farflash *) (addr) )
  #define _FILL_TEMP_WORD(addr,data) __AddrToZ24WordToR1R0ByteToSPMCR_SPM( (void __farflash *) (addr), data, 0x01 )
  #define _PAGE_ERASE(addr) __AddrToZ24ByteToSPMCR_SPM( (void __farflash *) (addr), 0x03 )
  #define _PAGE_WRITE(addr) __AddrToZ24ByteToSPMCR_SPM( (void __farflash *) (addr), 0x05 )
#endif

Как видите, всё есть.
Сергей Борщ
Цитата(arttab @ Jul 14 2006, 09:57) *
Люди, подскажите - есть ли в IAR функции для самопрограмирования? Очистить буфер, занести слово в буфер, записать буфер, биты защиты выстывить....
ой мама... "На колу мочало...". В intrinsics.h есть макросы
>Очистить буфер, занести слово в буфер,
_SPM_FILLTEMP(Addr,Data)
> записать буфер,
_SPM_PAGEWRITE(Addr)
>биты защиты выстывить
_SPM_LOCKBITS(Data)

Там же полезные
_SPM_ERASE(Addr)
_SPM_GET_LOCKBITS()
_SPM_GET_FUSEBITS()
Они вызывают "в IAR функции для самопрограмирования":
Код
__DataToR0ByteToSPMCR_SPM()
__AddrToZByteToSPMCR_SPM()
__AddrToZWordToR1R0ByteToSPMCR_SPM()
Или я опять вопроса не понял?
arttab
или я чего туплю или как....
не понимаю как ими воспользоваться.
__AddrToZByteToSPMCR_SPM((void __flash*)(Addr), 0x03)
сдесь понятно: номер страници и вперед
А я ковырялся с
/* SPM */

/*
__DataToR0ByteToSPMCR_SPM, pseudo code.
MOV R0,data
OUT SPMCR,byte
SPM
*/
__intrinsic void __DataToR0ByteToSPMCR_SPM(unsigned char data,
unsigned char byte);

и не всегда мог понять для чего они.
Получается надо смотреть, то что начинается с #define:

_SPM_LOCKBITS(Data) // где data 1 байт. установить биты защиты
_SPM_ERASE(Addr) // Addr 2 Байта 11-5 биты. стереть страницу
_SPM_FILLTEMP(Addr,Word) //Addr 2 Байта (4-0 биты), word 2 Байта. слово в буфер
_SPM_PAGEWRITE(Addr) //Addr 2 Байта 11-5 биты. запись страници
unsigned char t = _SPM_GET_LOCKBITS() //чтение байта защиты
unsigned char t =_SPM_GET_FUSEBITS() // чтение байта конфигурации

А вот что за эти команды:
#define _SPM_24_ERASE(Addr) и т.д. с цифрой 24?
Нехватает команды очиски буфера и макроса ожидания выпоkytybz операции.
Ладно, носом ткнули, буду еще смотреть аплек109. Спасибо
arttab
Бывае говоришь о чем то со спецом, все он говорить правильно, кратко, по существу, а потом вдруг понимаешь, - а здесь он погнал....
Причины по выше сказаному бывают разные: невнимательность например.
Посмотрел я внимательно аплекуху 910 и узрел:
1. В flash.h * Compiler : IAR C 3.10C Kickstart. И нетребо было 4.12 ставить.
2. В main #include "flash.h".
Библиотеку flash.h найти в папках IAR не удалось. Буду разбираться как появившимися в моем распоряжении функциями пользоваться.
Спасибо за помощь - самостоятельно я бы больше времени потратил. Если что ещё поспрашаю. Уж какие нибудь нюансы да появяться.
Сергей Борщ
Цитата(arttab @ Jul 14 2006, 12:08) *
или я чего туплю или как....
не понимаю как ими воспользоваться.

__intrinsic void __DataToR0ByteToSPMCR_SPM(unsigned char data, unsigned char byte);

и не всегда мог понять для чего они.

а... Я-то думал вы сначала даташит про bootloader прочитали...
Setting the Boot Loader Lock Bits by SPM To set the Boot Loader Lock Bits, write the desired data to R0, write “X0001001” to SPMCR and execute SPM within four clock cycles after writing SPMCR.
Интересно, что же может делать функция с загадочным названием __DataToR0ByteToSPMCR_SPM?
Цитата
А вот что за эти команды:
#define _SPM_24_ERASE(Addr) и т.д. с цифрой 24?
Не пользовался, но могу предположить что для процессоров с более 64К памяти, т.е. с адресом в 24 бита?
Цитата
Нехватает команды очиски буфера и макроса ожидания выпоkytybz операции.
Ну нет в функциях команды SPM очистки буфера The temporary buffer will auto-erase after a page write operation or by writing the RWWSRE bit in SPMCR. А макрос может выглядеть так: while(SPMCR & (1<<SPMEN));



Цитата(arttab @ Jul 15 2006, 14:42) *
2. В main #include "flash.h".
Библиотеку flash.h найти в папках IAR не удалось.
Согласно правилам языка высокого уровня С если имя файла в директиве #include указано в двойных кавычках то компилятор ищет его в текущей директории, т.е. в папке проекта. Если же в угловых - то в папках указанных компилятору в опциях как include path. Поэтому flash.h искать в папках IAR не имело смысла - он должен быть в исходниках от "аплекухи 910".
arttab
Цитата
Согласно правилам языка высокого уровня С если имя файла в директиве #include указано в двойных кавычках то компилятор ищет его в текущей директории, т.е. в папке проекта. Если же в угловых - то в папках указанных компилятору в опциях как include path. Поэтому flash.h искать в папках IAR не имело смысла - он должен быть в исходниках от "аплекухи 910".

Это я знаю. Но до меня не доходило такое
#define _GET_LOCK_BITS() __AddrToZByteToSPMCR_LPM( (void __flash *) 0x0001, 0x09 )
т.е. функции самопрограмирования в IAR есть, но для удобства их использования делаются присвоение и вызов с параметрами. А я в хелпе IAR искал и не мог найти таких команд.
Эх Си- 280 строчек- 914 Байт. Лень на асеме писать sad.gif
arttab
Новая проблема: пытаюсь сгенерить hex а IAR ругается
Fatal Error[e72]: Segment TINY_Z must be defined in a segment definition option (-Z, -b or -P)
В дебагере все легло ровно, а здесь проблемы. В какой должен быть выходной формат или в экстра опциях линкера прописать чего надо?
Сергей Борщ
Цитата(arttab @ Jul 17 2006, 12:47) *
Новая проблема: пытаюсь сгенерить hex а IAR ругается
Fatal Error[e72]: Segment TINY_Z must be defined in a segment definition option (-Z, -b or -P)
В дебагере все легло ровно, а здесь проблемы. В какой должен быть выходной формат или в экстра опциях линкера прописать чего надо?
Видимо в настройках проекта стоит настройка memory model: Tiny а файл .xcl взят с "s" на конце, т.е. для модели памяти Small. Измените настройку на Small и все должно заработать. Кстати, интересно как "В дебагере все легло ровно", ведь файл для дебаггера тоже генерит линкер и с теми же самыми параметрами... Или это после переключения target с debug на release? Тогда понятно - надо сравнить модель памяти и выбранный .xcl в обоих targets.
osnwt
Рекомендую посмотреть на мой проект Crypto-Boot (только как reference, а не образец для подражания - см. его README) на сайте разработчика USB драйвера для AVR. Возможно, часть вопросов снимется.

Там реализован USB boot loader для меги32, использующий программную реализацию USB. Загрузчик позволяет, в частности, перешивать код приложения по тому же USB интерфейсу, что и само приложение может использовать.

Загрузчик использует перемещение вектора прерывания в область бута для работы бута независимо от приложения (вопросы BOOTRST, и управления переключением вектора).

Загрузчик поддерживает работу с серийными номерами и версиями бута и приложения, в т.ч. чтение последних бутом из области приложения для передачи утилите на PC. Очевидно, такой же подход можно использовать и в обратном направлении - используя вызовы каких-то функций, размещенных в области загрузчика, из области приложения. Я бы для такой цели (если иного варианта не видится) использовал таблицу переходов типа rjmp на начало нужных функций в буте, размещенную по фиксированному адресу в области бута. Тогда на них можно будет ссылаться из независимо собранного приложения, прописав только их адреса (которые фиксированы и известны независимо от сборки бута. Как прописать - см. там же, как вызывается приложение по адресу 0 из бута. Тут будет обратная картина.

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

Проект, как там написано, без комментариев, только как reference (хотя у меня работает). На конкретный вопрос ответить смогу. На вопрос "как все это собрать, чтобы заработало" - нет. Проект искать тут, называется Crypto-Boot (с парапланом в качестве иллюстрации). Собирался под IAR 4.12.
arttab
Нашел разницу в дебугере и релайсе: general options / system configurations снял галку и все пошло. Модель памяти оставил tiny.
файл .xcl взят с "s" на конце. Попробую запустить.
Спасибо. Пример посмотрю.
IgorKossak
Цитата(arttab @ Jul 18 2006, 04:40) *
...Модель памяти оставил tiny.
файл .xcl взят с "s" на конце....

Зачем такая несовместимость?
Установите модель памяти small. Если работает с моделью tiny, это не значит, что это правильно.
arttab
Лучше конечносделать как надо, но для small 1040 байт, а tiny 970. Где то может и сыграть размер кода.
Сергей Борщ
Цитата(arttab @ Jul 18 2006, 10:02) *
Лучше конечносделать как надо, но для small 1040 байт, а tiny 970. Где то может и сыграть размер кода.
Пока хватает 256 байт ОЗУ можно и Tiny, но тогда и .xcl надо брать для модели Tiny, т.е. с "t" на конце.
prottoss
Цитата(Сергей Борщ @ Jul 18 2006, 15:37) *
Цитата(arttab @ Jul 18 2006, 10:02) *

Лучше конечносделать как надо, но для small 1040 байт, а tiny 970. Где то может и сыграть размер кода.
Пока хватает 256 байт ОЗУ можно и Tiny, но тогда и .xcl надо брать для модели Tiny, т.е. с "t" на конце.


ИМХО лучше делать исходник так, чтобы работало на всех моделях памяти...
arttab
Так до меня и не дошли все команды для самопрогаммирования AVR109 - Self-programming:
_WAIT_FOR_SPM(); // ожидание готовности
_ENABLE_RWW_SECTION(); // очиска буфера и разрешение записи в сегмент RWW
_PAGE_WRITE( address); // запись в страницу по адресу address
#pragma diag_suppress=Pe1053 // Suppress warning for conversion from long-type address to flash ptr.
#pragma diag_default=Pe1053 // Back to default.
эти 2 прагмы выкл. и вкл. ругань на преобразование переменной
_FILL_TEMP_WORD(*address,data); // это запись в буфер?

Как я понял адреса в буфере это биты с 0 по 4, адреса страниц это с 5 по 11 биты.
данные для загрузки в буфер 2 байта (unsigned short).
Чтение из flash _LOAD_PROGRAM_MEMORY((address )
не понял так же что за преобразование адресов address << 1
prottoss
Цитата(arttab @ Jul 18 2006, 17:43) *
Так до меня и не дошли все команды для самопрогаммирования AVR109 - Self-programming:
_WAIT_FOR_SPM(); // ожидание готовности
_ENABLE_RWW_SECTION(); // очиска буфера и разрешение записи в сегмент RWW
_PAGE_WRITE( address); // запись в страницу по адресу address
#pragma diag_suppress=Pe1053 // Suppress warning for conversion from long-type address to flash ptr.
#pragma diag_default=Pe1053 // Back to default.
эти 2 прагмы выкл. и вкл. ругань на преобразование переменной
_FILL_TEMP_WORD(*address,data); // это запись в буфер?

Как я понял адреса в буфере это биты с 0 по 4, адреса страниц это с 5 по 11 биты.
данные для загрузки в буфер 2 байта (unsigned short).
Чтение из flash _LOAD_PROGRAM_MEMORY((address )
не понял так же что за преобразование адресов address << 1
Я Вам предлагаю не заморачиваться с AVR109, (хотя и не забывать про его исходники), а почитать даташит на любой MegaAVR, а именно раздел Boot Loader Support -> Self Programming
arttab
Рекомендую читать вопрос и весь топик, а не часть. Я хочу сделать загрузчик в IAR на Си. максимально использовав возможности IAR.
Вопрос остался. Видимо предется методом научного тыка
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.