реклама на сайте
подробности

 
 
> Никак не пойму как работае IAP, Никак не пойму как работае IAP
Metallist64
сообщение Jun 14 2011, 08:36
Сообщение #1


Частый гость
**

Группа: Участник
Сообщений: 103
Регистрация: 29-01-08
Пользователь №: 34 558



Добрый день уважаемый ALL!
Использую LPC2367 + Keil+RL. Встал вопрос обновления прошивки.
Планирую записывать ее во внешнюю флэшку. Затем читать и программировать механизмом IAP.
Проблема в следующем: не въеду как работает этот IAP.
Понял, что есть область адресов для программы, есть кокой-то загрузчик. Но не понимаю как осуществляется переход между ними.
Кто сталкивался, прошу помощи.
Go to the top of the page
 
+Quote Post
2 страниц V   1 2 >  
Start new topic
Ответов (1 - 14)
kovigor
сообщение Jun 14 2011, 09:26
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 5 273
Регистрация: 30-03-10
Пользователь №: 56 295



Цитата(Metallist64 @ Jun 14 2011, 11:36) *
Добрый день уважаемый ALL!
Использую LPC2367 + Keil+RL. Встал вопрос обновления прошивки.
Планирую записывать ее во внешнюю флэшку. Затем читать и программировать механизмом IAP.
Проблема в следующем: не въеду как работает этот IAP.
Понял, что есть область адресов для программы, есть кокой-то загрузчик. Но не понимаю как осуществляется переход между ними.
Кто сталкивался, прошу помощи.


Вызываются функции загрузчика через указатели на них. У NXP все расписано в аппнотах. Например:

http://www.nxp.com/documents/application_note/AN10256.pdf

Если надо, могу прислать проект для LPC214x

Сообщение отредактировал kovigor - Jun 14 2011, 09:29
Go to the top of the page
 
+Quote Post
Metallist64
сообщение Jun 14 2011, 10:13
Сообщение #3


Частый гость
**

Группа: Участник
Сообщений: 103
Регистрация: 29-01-08
Пользователь №: 34 558



Цитата
Вызываются функции загрузчика через указатели на них. У NXP все расписано в аппнотах.

Вот вот здесь собственно и начинаются непонятки:
1. После перехода к загрузчику(и его выполнения?), насколько я понимаю, должен следовать мой код?
2. Насколько я понял максимальный разъмер кода - 8кб ? Т.к. он будет расположен в области загрузчика?
3. Слышал, что нужно переписывать таблицу векторов прерывай, так ли это?

PS Апноут прочел. Но к сожалению не понимаю последовательности процесса.
Go to the top of the page
 
+Quote Post
kovigor
сообщение Jun 14 2011, 10:26
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 5 273
Регистрация: 30-03-10
Пользователь №: 56 295



Цитата(Metallist64 @ Jun 14 2011, 13:13) *
Вот вот здесь собственно и начинаются непонятки:
1. После перехода к загрузчику(и его выполнения?), насколько я понимаю, должен следовать мой код?
2. Насколько я понял максимальный разъмер кода - 8кб ? Т.к. он будет расположен в области загрузчика?
3. Слышал, что нужно переписывать таблицу векторов прерывай, так ли это?


1. И до, и после. Вызовы функций загрузчика вставляются в требуемые места вашей программы.
2. См. описание функций загрузчика. В функцию записи передаются адреса источника и приемника, а никак не сами записываемые данные.
3. Не совсем. Вы просто можете запретить прерывания на время модификации Flash. Альтернатива - скопировать таблицу векторов в ОЗУ, указать на эту копию процессору и разместить обработчики прерываний и все требуемое для их работы в ОЗУ. тогда прерывания смогут обрабатываться даже во время записи во Flash ...

Сообщение отредактировал kovigor - Jun 14 2011, 10:27
Go to the top of the page
 
+Quote Post
Metallist64
сообщение Jun 14 2011, 11:29
Сообщение #5


Частый гость
**

Группа: Участник
Сообщений: 103
Регистрация: 29-01-08
Пользователь №: 34 558



Цитата(kovigor @ Jun 14 2011, 14:26) *
1. И до, и после. Вызовы функций загрузчика вставляются в требуемые места вашей программы.
2. См. описание функций загрузчика. В функцию записи передаются адреса источника и приемника, а никак не сами записываемые данные.
3. Не совсем. Вы просто можете запретить прерывания на время модификации Flash. Альтернатива - скопировать таблицу векторов в ОЗУ, указать на эту копию процессору и разместить обработчики прерываний и все требуемое для их работы в ОЗУ. тогда прерывания смогут обрабатываться даже во время записи во Flash ...


Т.е. насколько я понял, я должен записываться код со следующего свободного сектора и затем как-то переходить именно в эту область ?
Go to the top of the page
 
+Quote Post
kovigor
сообщение Jun 14 2011, 11:52
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 5 273
Регистрация: 30-03-10
Пользователь №: 56 295



Цитата(Metallist64 @ Jun 14 2011, 14:29) *
Т.е. насколько я понял, я должен записываться код со следующего свободного сектора и затем как-то переходить именно в эту область ?


А зачем туда переходить ? Стираете сектор и записываете в него новые данные (блоками размером не более 4096 байт). В User Manual'е все это подробно расписано. После обновления всех запланированных секторов можете просто использовать их новое содержимое по своему усмотрению (например, если обновлялись данные пользователя). А если речь идет об обновлении прошивки, по проще всего будет после успешного обновления перегрузиться, используя WatchDog. Так вы "перейдете именно в эту область". Функции, модифицирующие Flash, следует расположить в ОЗУ, чтобы не было конфликтов и зависаний при одновременной модификации Flash и выборки из нее кодов команд или данных ...
Go to the top of the page
 
+Quote Post
Metallist64
сообщение Jun 16 2011, 10:32
Сообщение #7


Частый гость
**

Группа: Участник
Сообщений: 103
Регистрация: 29-01-08
Пользователь №: 34 558



Цитата
Функции, модифицирующие Flash, следует расположить в ОЗУ, чтобы не было конфликтов и зависаний при одновременной модификации Flash и выборки из нее кодов команд или данных ..


На сколько я понимаю физически флэш память одна. Она просто логически разделена(судя по карте памяти) на разелы BOOT и скажем так пользовательский код?

Сам код, который будет обновлять флэш будет находиться в области зарузчика ? И писать пользовательский код туда нельзя. Судя по карте памяти в нем есть как ROM так FLASH области?

Таким образом общий объем памяти складывается из = BOOT ROM + BOOT FLASH + USER CODE FLASH ?

Опять таки, насколько я понял, что для LPC2367 объем BOOT области = 8кб. И писать тудо ничего ненадо? Там лежат именно те самые функции IAP, я должен только использовать их, вызывая и передавая аргументы?
Go to the top of the page
 
+Quote Post
mempfis_
сообщение Jun 19 2011, 12:21
Сообщение #8


Профессионал
*****

Группа: Свой
Сообщений: 1 001
Регистрация: 27-06-06
Пользователь №: 18 409



Цитата(Metallist64 @ Jun 16 2011, 13:32) *
На сколько я понимаю физически флэш память одна. Она просто логически разделена(судя по карте памяти) на разелы BOOT и скажем так пользовательский код?

Сам код, который будет обновлять флэш будет находиться в области зарузчика ? И писать пользовательский код туда нельзя. Судя по карте памяти в нем есть как ROM так FLASH области?

Таким образом общий объем памяти складывается из = BOOT ROM + BOOT FLASH + USER CODE FLASH ?

Опять таки, насколько я понял, что для LPC2367 объем BOOT области = 8кб. И писать тудо ничего ненадо? Там лежат именно те самые функции IAP, я должен только использовать их, вызывая и передавая аргументы?


FLASH одна и имеет линейное адресное пространство от и до.
Вы можете выделить под Ваш загрузчик скажем первые 8к (2 первых сектора по 4к, если их будет мало добавите сколько нужно - для lpc23хх нет разграничений flash на boot не boot области как у атмег). В этой области разместите код загрузчика который будет каким-либо образом принимать прошивку (по uart или как сделано у меня 122к зашифрованной прошивки хранятся во внешней flash-памяти). Код загрузчика анализирует наличие прошивки, закидывает в буффер скажем 4к блок прошивки приложения, из IAP вызывает процедуру подготовки соотв. сектора, процедуру стирания и потом процедуру записи. Там по сути всё настолько просто что работает с первого раза (скажем у меня за полдня получилось полностью освоить код работы с IAP и написать загрузчик для lpc2368).

CODE
//-----------------------------------------
//стирание выбранного сектора
unsigned int eraseSector(unsigned int SECTOR)
{
unsigned int status=0;

//---------------------------------------
//подготовка сектора
status = iapSelectSector(SECTOR, SECTOR);
if(status != IAP_CMD_SUCCESS)
{
return 0; //сбой подготовки
}
//---------------------------------------


//---------------------------------------
//стирание сектора
__disable_interrupt();
status = iapEraseSector(SECTOR, SECTOR);
__enable_interrupt();

if(status != IAP_CMD_SUCCESS)
{
return 0; //сбой стирания
}
else
{
return 1; //стирание OK
}
//---------------------------------------
}
//-----------------------------------------

//-----------------------------------------
//запись вектора
unsigned int writeSector(unsigned int* pData, unsigned int SECTOR, unsigned int addr, unsigned int size)
{
unsigned int status=0;

//---------------------------------------
//подготовка сектора
status = iapSelectSector(SECTOR, SECTOR);
if(status != IAP_CMD_SUCCESS)
{
return 0; //сбой подготовки
}
//---------------------------------------

//---------------------------------------
//запись сектора
__disable_interrupt();
status = iapRamToFlash( addr, (unsigned int) pData, size);
__enable_interrupt();
if(status != IAP_CMD_SUCCESS)
{
return 0; //сбой записи
}
else
{
return 1; //запись OK
}
//---------------------------------------

}
//-----------------------


Сообщение отредактировал mempfis_ - Jun 19 2011, 12:23
Go to the top of the page
 
+Quote Post
Metallist64
сообщение Jun 20 2011, 06:29
Сообщение #9


Частый гость
**

Группа: Участник
Сообщений: 103
Регистрация: 29-01-08
Пользователь №: 34 558



Большое спасибо за пример и пояснение.
С функциями более или менее разобрался.
Но есть еще пара вопросиков:
А на уровне проекта это как осуществляется?
Создаются 2 проекта с разными рабочими областями? или в одном проекте указывается где какой код должен лежать?

Заранее спасибо.

Go to the top of the page
 
+Quote Post
mempfis_
сообщение Jun 20 2011, 16:34
Сообщение #10


Профессионал
*****

Группа: Свой
Сообщений: 1 001
Регистрация: 27-06-06
Пользователь №: 18 409



Цитата(Metallist64 @ Jun 20 2011, 09:29) *
Большое спасибо за пример и пояснение.
С функциями более или менее разобрался.
Но есть еще пара вопросиков:
А на уровне проекта это как осуществляется?
Создаются 2 проекта с разными рабочими областями? или в одном проекте указывается где какой код должен лежать?

Заранее спасибо.


У меня это 2 отдельных проекта. Связаны они между собой только начальным адресом приложения во flash.
В бутлоадере в файле линкера flash ограничена 8к. Выделен сегмент под CRP.
В коде бутлоадера гдето прописывается уровень защиты
Код
//-------------------------------------------
//устанавливаем защиту
#define CRP1 0x12345678ul
#define CRP2 0x87654321ul
#define CRP3 0x43218765ul //этот уровень защиты убъёт процессор!!!

#pragma location = "CRP_section"
__root const unsigned long crp = 0x87654321ul;
//-------------------------------------------


вызов приложения из бутлоадера осуществляется так:

Код
void (*app) (); //указатель на приложение

#define APPL_START_ADDR 0x00002000 //стартовый адрес расположения приложения во flash

app = (void(*)()) APPL_START_ADDR;
app();


В icf-файле приложения необходимо указать линкеру что вектора прерываний находятся не по нулевому адресу. Ну и ограничить flash.

Пишу в IAR. Прмер icf-файла для бутлоадера.

CODE
/*###ICF### Section handled by ICF editor, don't touch! ****/
/*-Editor annotation file-*/
/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\a_v1_0.xml" */
/*-Specials-*/
define symbol __ICFEDIT_intvec_start__ = 0x00000000;
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__ = 0x00000200;
define symbol __ICFEDIT_region_ROM_end__ = 0x00002000;
define symbol __ICFEDIT_region_RAM_start__ = 0x40000040;
define symbol __ICFEDIT_region_RAM_end__ = 0x40007FDF;
/*-Sizes-*/
define symbol __ICFEDIT_size_cstack__ = 0x400;
define symbol __ICFEDIT_size_svcstack__ = 0x100;
define symbol __ICFEDIT_size_irqstack__ = 0x100;
define symbol __ICFEDIT_size_fiqstack__ = 0x40;
define symbol __ICFEDIT_size_undstack__ = 0x10;
define symbol __ICFEDIT_size_abtstack__ = 0x10;
define symbol __ICFEDIT_size_heap__ = 0x2000;
/**** End of ICF editor section. ###ICF###*/


define memory mem with size = 4G;
define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__];
define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__];

define symbol __region_USB_DMA_RAM_start__ = 0x7FD00000;
define symbol __region_USB_DMA_RAM_end__ = 0x7FD01FFF;
define region USB_DMA_RAM_region= mem:[from __region_USB_DMA_RAM_start__ to __region_USB_DMA_RAM_end__];

define symbol __region_EMAC_DMA_RAM_start__ = 0x7FE00000;
define symbol __region_EMAC_DMA_RAM_end__ = 0x7FE03FFF;
define region EMAC_DMA_RAM_region= mem:[from __region_EMAC_DMA_RAM_start__ to __region_EMAC_DMA_RAM_end__];

define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };
define block SVC_STACK with alignment = 8, size = __ICFEDIT_size_svcstack__ { };
define block IRQ_STACK with alignment = 8, size = __ICFEDIT_size_irqstack__ { };
define block FIQ_STACK with alignment = 8, size = __ICFEDIT_size_fiqstack__ { };
define block UND_STACK with alignment = 8, size = __ICFEDIT_size_undstack__ { };
define block ABT_STACK with alignment = 8, size = __ICFEDIT_size_abtstack__ { };
define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { };

initialize by copy { readwrite };
do not initialize { section .noinit };
do not initialize { section USB_DMA_RAM };
do not initialize { section EMAC_DMA_RAM };

place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };

place in ROM_region { readonly };
place in RAM_region { readwrite,
block CSTACK, block SVC_STACK, block IRQ_STACK, block FIQ_STACK,
block UND_STACK, block ABT_STACK, block HEAP };
place in USB_DMA_RAM_region
{ section USB_DMA_RAM };
place in EMAC_DMA_RAM_region
{ section EMAC_DMA_RAM };


place at address mem: 0x000001FC { readonly section CRP_section };


Пример icf-файла приложения:

CODE
/*###ICF### Section handled by ICF editor, don't touch! ****/
/*-Editor annotation file-*/
/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\a_v1_0.xml" */
/*-Specials-*/
define symbol __ICFEDIT_intvec_start__ = 0x00002000;
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__ = 0x00002044;
define symbol __ICFEDIT_region_ROM_end__ = 0x0001FFFF;
define symbol __ICFEDIT_region_RAM_start__ = 0x40000040;
define symbol __ICFEDIT_region_RAM_end__ = 0x40007FFF;
/*-Sizes-*/
define symbol __ICFEDIT_size_cstack__ = 0x400;
define symbol __ICFEDIT_size_svcstack__ = 0x100;
define symbol __ICFEDIT_size_irqstack__ = 0x100;
define symbol __ICFEDIT_size_fiqstack__ = 0x40;
define symbol __ICFEDIT_size_undstack__ = 0x10;
define symbol __ICFEDIT_size_abtstack__ = 0x10;
define symbol __ICFEDIT_size_heap__ = 0x2000;
/**** End of ICF editor section. ###ICF###*/


define memory mem with size = 4G;
define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__];
define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__];

define symbol __region_USB_DMA_RAM_start__ = 0x7FD00000;
define symbol __region_USB_DMA_RAM_end__ = 0x7FD01FFF;
define region USB_DMA_RAM_region= mem:[from __region_USB_DMA_RAM_start__ to __region_USB_DMA_RAM_end__];

define symbol __region_EMAC_DMA_RAM_start__ = 0x7FE00000;
define symbol __region_EMAC_DMA_RAM_end__ = 0x7FE03FFF;
define region EMAC_DMA_RAM_region= mem:[from __region_EMAC_DMA_RAM_start__ to __region_EMAC_DMA_RAM_end__];

define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };
define block SVC_STACK with alignment = 8, size = __ICFEDIT_size_svcstack__ { };
define block IRQ_STACK with alignment = 8, size = __ICFEDIT_size_irqstack__ { };
define block FIQ_STACK with alignment = 8, size = __ICFEDIT_size_fiqstack__ { };
define block UND_STACK with alignment = 8, size = __ICFEDIT_size_undstack__ { };
define block ABT_STACK with alignment = 8, size = __ICFEDIT_size_abtstack__ { };
define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { };

initialize by copy { readwrite };
do not initialize { section .noinit };
do not initialize { section USB_DMA_RAM };
do not initialize { section EMAC_DMA_RAM };

place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };

place in ROM_region { readonly };
place in RAM_region { readwrite,
block CSTACK, block SVC_STACK, block IRQ_STACK, block FIQ_STACK,
block UND_STACK, block ABT_STACK, block HEAP };
place in USB_DMA_RAM_region
{ section USB_DMA_RAM };
place in EMAC_DMA_RAM_region
{ section EMAC_DMA_RAM };

Go to the top of the page
 
+Quote Post
Metallist64
сообщение Jun 21 2011, 05:54
Сообщение #11


Частый гость
**

Группа: Участник
Сообщений: 103
Регистрация: 29-01-08
Пользователь №: 34 558



Большое спасибо!
Пойду разбираться!
Go to the top of the page
 
+Quote Post
Lexy_one
сообщение Jul 11 2011, 11:34
Сообщение #12


Частый гость
**

Группа: Участник
Сообщений: 90
Регистрация: 28-07-09
Из: Чернигов
Пользователь №: 51 621



Здраствуйте я прочитал топик... вроде большынство доводов понятно..
есть один вопросик:
Так все таки нужно ремап далать или нет? Или можно коду загрузчика работать из флеш?
Go to the top of the page
 
+Quote Post
kovigor
сообщение Jul 12 2011, 08:26
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 5 273
Регистрация: 30-03-10
Пользователь №: 56 295



Цитата(Lexy_one @ Jul 11 2011, 14:34) *
Здраствуйте я прочитал топик... вроде большынство доводов понятно..
есть один вопросик:
Так все таки нужно ремап далать или нет? Или можно коду загрузчика работать из флеш?

Ремап таблицы векторов нужен, если вы не запрещаете прерывания на время выполнения IAP. Иначе не нужен.
Go to the top of the page
 
+Quote Post
skripach
сообщение Jul 12 2011, 08:43
Сообщение #14


■ ■ ■ ■
*****

Группа: Свой
Сообщений: 1 100
Регистрация: 9-08-06
Пользователь №: 19 443



Цитата
Или можно коду загрузчика работать из флеш?

Нужно.


--------------------
Делай что должен и будь что будет.
Go to the top of the page
 
+Quote Post
Lexy_one
сообщение Jul 12 2011, 10:40
Сообщение #15


Частый гость
**

Группа: Участник
Сообщений: 90
Регистрация: 28-07-09
Из: Чернигов
Пользователь №: 51 621



И еще пара вопросиков sm.gif
1) допустим у меня приложение начинается с адреса 0х020000. достаточно ли просто для старта приложения перейти по указанному адресу? или нет?
2) в НЕХ файле приложения есть запись с типом 05 (линейный адрес старта) что с ней делать? можно ли ее проигнорировать или нет? в описании стандарта Intel-HEX указанно что эта запись указывает на адрес с которого начинается исполнение объектного файла - значит ее надо кудато запихнуть, а куда...?

Подскажите кто знает!

Сообщение отредактировал Lexy_one - Jul 13 2011, 05:45
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th July 2025 - 21:48
Рейтинг@Mail.ru


Страница сгенерированна за 0.01515 секунд с 7
ELECTRONIX ©2004-2016