Необходимо иметь возможность обновлять микрокод мк через последовательный интерфейс. Для экономии места в мк (МЕГА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
Jul 5 2006, 15:18
посмотрите в примере от Atmel. Там не совсем то что вы хотите, но зато показано как в ИАР писать из бута в память кода.
Это приложение к ан109. уже взял, уже ковыряю.... Куча вопросов по С++. Во строеном в IAR хелпе мало и фигово описано.
Вопрос к тем кто делал в одном проекте с прогой и бутлоадер:
Для последующего "срастания" обновления с функциями лежащими в бутлоадере, Вы использовали при вызове функций указатели на них? А указатели приравнивали к адресам получившиеся в бутлоадере.
Что означает __C_task void loader(void)?
Я только понял что это влияет на модель памяти и размещение используемых в функции переменных
Забыл зарегистрироваться. От гостя можно удалить
Если я правильно понял, то:
_C - указывает что нужно сгенерить сегмент. Начальный адрес указывается где-то далее;
_task - объявляет функцию как не использующию стек. А зачем это и для чего?
Адреса прерываний нужно указывать самому (они будут в загрузчике).
напрмер так?
#pragma vector=0xC1A
__interrupt void my_interrupt_handler(void)
{
asm("NOP");
}
Еще вопрос по адресам прерываний:
В табл 18 и 19 ан даны адреса.
В табл 19 Reset adres 0x0000 Interrupt vector stsrt adres 0x0001. И это смещение на 1 и при переносе векторов в область загрузчика.
Почему смещение на 1?
IgorKossak
Jul 6 2006, 07:08
Цитата(arttab @ Jul 6 2006, 07:11)

Если я правильно понял, то:
_C - указывает что нужно сгенерить сегмент. Начальный адрес указывается где-то далее;
_task - объявляет функцию как не использующию стек. А зачем это и для чего?
Вы не правильно поняли.
_C_task это то же что и __task - указание компилятору не сохранять регистры в прологе функции и не восстанавливать в эпилоге.
Применяется в основном для тех функций, из которых не ожидается выходить, т. е. main или различные функции процессов при применении RTOS.
Спасибо! Хоть один не отсылает к докам по IARу. В них не все понятно.
Если я правильно понял, то в примерах bootloaderов это фича для красоты.
А по адресам прерываний на Мегу8 ошибка столо быть: начинаются они или с 0х0000 или с начала секции загрузчика. В последнем случае адреса надо самому указать векторов.
А как объяснить IARу что main находиться в секции бутлоадера и в вектор прерывания по ресету в бутлоадере лег правильный адрем main?
Цитата(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
Jul 6 2006, 12:46
Цитата(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 это не существенно.
Просто и сердито, и никакой головной боли, и проекты могут не зависеть один от другого, особенно если применяются раздельные контрольные суммы для приложения и бутлоадера.
Может можно и совместно использовать некоторые функции, но это как по мне слегка вяжет руки.
Ограниченость памяти меги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 что бы было верно?
Есть вообще возможность разместить 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();
}
Цитата(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
Сергей Борщ
Jul 7 2006, 07:24
Цитата(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
Jul 7 2006, 07:32
arttab, Вы взяли для модифицирования не тот конфигурационный файл.
Чтобы было намного гибче и предсказуемее, сделайте следующее:
1. lnkm8s.xcl из папки \avr\config это то что нужно, скопируйте этот файл в папку проекта
2. в General Options снимите галочку в поле Configure system using dialogs...
3. в опциях XLINK/Include в поле XCL file name укажите путь к Вашему файлу xcl.
Что касается двух таблиц прерываний, то это скорее всего невозможно сделать автоматически. В этой среде поддерживается идеология: один проект - одно распределение памяти.
В таком случае более универсальным будет подход, о котором я уже говорил, сделать два проекта в одном рабочем пространстве.
Спасибо всем. разбираюсь...
А что значит:
Цитата
сделать два проекта в одном рабочем пространстве
? Я понял что в одном проекте есть и bootloader и обновляемая прога. Или Вы имели ввиду адресное пространство мк?
для линкера и экстра опций нужно указывать в байтах или в словах?
IgorKossak
Jul 7 2006, 08:16
Цитата(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 гамму МК.
Сергей Борщ,
в указаном Вами файле
RSEG LOADER:CODE:NOROOT(1)
менять так:
RSEG LOADER:CODE:NOROOT(1) ?
Попробую сделать отдельный проект для загрузчика
Сергей Борщ
Jul 7 2006, 09:37
Цитата(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
Тогда при переносе проекта в другую папку не придется переписывать путь заново.
Начал делать отдельно 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
Jul 10 2006, 06:53
Цитата(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
Jul 10 2006, 14:15
Спасибо за подсказку. В 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
Сергей Борщ
Jul 10 2006, 17:59
Цитата(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

Ну если описать толково, то beer_warrior не должен отказаться включить в FAQ :-)
arttab
Jul 11 2006, 02:05
Цитата
Обрати внимание на строчку .xcl:
-H1895 -h(CODE)00-25
Увидел. Исправил -H1895 -h(CODE)1C0-1C25
Кстати, в примерах видел выражения типа FLASH_SIZE-BOOT_SIZE, но у меня так сделать не вышло. Нужно какуюто библиотеку прицепить?
Цитата
Не совсем понял о каком буфере идет речь, но если о команде SPM, то обрати внимание на функции и макросы из intrinsics.h:
Оно. Я не ясно выразился, но Вы правильно поняли. Поразбараюсь с intrinsics.h
Спасибо, буду дальше разбираться
arttab
Jul 11 2006, 03:03
Сергей Борщ? А где лежит файл intrinsics.h? не нашел в каталоге IAR. Или это в старшей версии есть?
Сергей Борщ
Jul 11 2006, 09:00
Цитата(arttab @ Jul 11 2006, 06:03)

Сергей Борщ? А где лежит файл intrinsics.h? не нашел в каталоге IAR. Или это в старшей версии есть?
Не знаю что считать старшей версией, у меня в 4.10B лежит в каталоге IAR\AVR\INC
arttab
Jul 11 2006, 09:36
Цитата
Не знаю что считать старшей версией
Имел в виду цифры версии. В 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)
Сергей Борщ
Jul 11 2006, 14:15
Цитата(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
Jul 12 2006, 09:02
Уф, переполз на 4.12А. с трудом.
intrinsics.h нужно подключить к проекту или она автоматом как только сделаю вызов ее функций?
выражения типа FLASH_SIZE-BOOT_SIZE работают в этой версии?
Пока поразбираюсь SPM функциями intrinsics.h
arttab
Jul 13 2006, 07:33
Сергей Борщ, не моглибы Вы прокоментировать мои изыскания:
/*
__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);
Ошибка или это что то специфическое?
//---------------------------------------
Что то не понял я с этой библиотекой
И как Вы управляли самопрограммированием (какие функции использовали для стирания, записи, ожидания готовности...).
Сергей Борщ
Jul 13 2006, 08:20
Цитата(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
Jul 13 2006, 09:28
Спасибо. Просто я не понял как ими воспользоваться. Т.е. какие функции вызывать с какими параметрами. попробую еще в help поискать на IAR
arttab
Jul 14 2006, 06:57
Люди, подскажите - есть ли в IAR функции для самопрограмирования? Очистить буфер, занести слово в буфер, записать буфер, биты защиты выстывить....
IgorKossak
Jul 14 2006, 08:24
Цитата(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
Как видите, всё есть.
Сергей Борщ
Jul 14 2006, 08:32
Цитата(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
Jul 14 2006, 09:08
или я чего туплю или как....
не понимаю как ими воспользоваться.
__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
Jul 15 2006, 11:42
Бывае говоришь о чем то со спецом, все он говорить правильно, кратко, по существу, а потом вдруг понимаешь, - а здесь он погнал....
Причины по выше сказаному бывают разные: невнимательность например.
Посмотрел я внимательно аплекуху 910 и узрел:
1. В flash.h * Compiler : IAR C 3.10C Kickstart. И нетребо было 4.12 ставить.
2. В main #include "flash.h".
Библиотеку flash.h найти в папках IAR не удалось. Буду разбираться как появившимися в моем распоряжении функциями пользоваться.
Спасибо за помощь - самостоятельно я бы больше времени потратил. Если что ещё поспрашаю. Уж какие нибудь нюансы да появяться.
Сергей Борщ
Jul 17 2006, 07:59
Цитата(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
Jul 17 2006, 08:10
Цитата
Согласно правилам языка высокого уровня С если имя файла в директиве #include указано в двойных кавычках то компилятор ищет его в текущей директории, т.е. в папке проекта. Если же в угловых - то в папках указанных компилятору в опциях как include path. Поэтому flash.h искать в папках IAR не имело смысла - он должен быть в исходниках от "аплекухи 910".
Это я знаю. Но до меня не доходило такое
#define _GET_LOCK_BITS() __AddrToZByteToSPMCR_LPM( (void __flash *) 0x0001, 0x09 )
т.е. функции самопрограмирования в IAR есть, но для удобства их использования делаются присвоение и вызов с параметрами. А я в хелпе IAR искал и не мог найти таких команд.
Эх Си- 280 строчек- 914 Байт. Лень на асеме писать
arttab
Jul 17 2006, 09:47
Новая проблема: пытаюсь сгенерить hex а IAR ругается
Fatal Error[e72]: Segment TINY_Z must be defined in a segment definition option (-Z, -b or -P)
В дебагере все легло ровно, а здесь проблемы. В какой должен быть выходной формат или в экстра опциях линкера прописать чего надо?
Сергей Борщ
Jul 17 2006, 10:26
Цитата(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.
Рекомендую посмотреть на мой проект 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
Jul 18 2006, 01:40
Нашел разницу в дебугере и релайсе: general options / system configurations снял галку и все пошло. Модель памяти оставил tiny.
файл .xcl взят с "s" на конце. Попробую запустить.
Спасибо. Пример посмотрю.
IgorKossak
Jul 18 2006, 06:21
Цитата(arttab @ Jul 18 2006, 04:40)

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

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

Цитата(arttab @ Jul 18 2006, 10:02)

Лучше конечносделать как надо, но для small 1040 байт, а tiny 970. Где то может и сыграть размер кода.
Пока хватает 256 байт ОЗУ можно и Tiny, но тогда и .xcl надо брать для модели Tiny, т.е. с "t" на конце.
ИМХО лучше делать исходник так, чтобы работало на всех моделях памяти...
arttab
Jul 18 2006, 09: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
prottoss
Jul 18 2006, 10:03
Цитата(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
Jul 19 2006, 02:30
Рекомендую читать вопрос и весь топик, а не часть. Я хочу сделать загрузчик в IAR на Си. максимально использовав возможности IAR.
Вопрос остался. Видимо предется методом научного тыка
Для просмотра полной версии этой страницы, пожалуйста,
пройдите по ссылке.