|
|
  |
LPC11xx не стартует код из своего бутлоадера |
|
|
|
Oct 21 2010, 10:42
|

Частый гость
 
Группа: Свой
Сообщений: 173
Регистрация: 30-11-05
Из: San Francisco
Пользователь №: 11 593

|
Использую LPC1114. По доке вроде все понятно. Свой бутлоадер код во флеш прописал. для старта делаю следующее: 1. копирую 48 векторов прерывания основной программы в ОЗУ с адреса 0x10000000 2. Делаю ремап LPC_SYSCON->SYSMEMREMAP = 0x01; т.е. отобрашаем вектора из ОЗУ в начало адресного простанства 3. инициализирую SP и PC данными из первых 8-ми байт моей проги. Все это выглядит так: Код __asm void boot_jump( uint32_t address ) { LDR R1, [R0] ;Load new stack pointer address MOV R13, R1 LDR R1, [R0, #4];Load new program counter address BX R1 }
void run(unsigned long address) { unsigned long *dst, size; const unsigned long *src; // Copy vectors table src = (unsigned long *)address; dst = (unsigned long *)0x10000000; size = VECTORS_TABLE_SIZE >> 2; do { *dst++ = *src++; } while (--size);
LPC_SYSCON->SYSMEMREMAP = 0x01; /* remap to SRAM */
boot_jump(address); } В результате поведение непредсказуемое. то висит, то попадает куда-то в середину бутлоадера. Если убрать ремап, то целевая прога запускается, но естественно с векторами из флеша. Что я забываю в этой схеме?
|
|
|
|
|
Oct 21 2010, 12:12
|
Участник

Группа: Участник
Сообщений: 32
Регистрация: 21-09-10
Пользователь №: 59 626

|
У меня та же проблема. Пробую на отладке LPCXpresso, среда CodeRed. Процессор LPC1114. Я взял проект blinky из примеров и попытался просто скопировать вектора в ОЗУ и сделать ремап. (соотв. область озу зарезервирована в скрипте линкера). Программа вылетает в HardFault exception. Написал вопрос в LPCXpresso forum. Жду ответа... У меня самого идеи кончились. В дебаг режиме, при пошаговом выполнении, вылетает на команде bl. Вот код функции Reset_Handler из примера с моими изменениями: Код void Reset_Handler(void) { unsigned char *pulSrc, *pulDest;
// // Copy the data segment initializers from flash to SRAM. // pulSrc = &_etext; for(pulDest = &_data; pulDest < &_edata; ) { *pulDest++ = *pulSrc++; }
// // Zero fill the bss segment. // for(pulDest = &_bss; pulDest < &_ebss; pulDest++) *pulDest = 0;
// Copying the vector table to sram unsigned char i; unsigned char * vectDest; unsigned char * vectSrc;
vectDest = (unsigned char *)(0x10000000); vectSrc = (unsigned char *)(0x00000000); for (i = 0; i < 0xC0; i++) { *vectDest++ = *vectSrc++; };
// Remap LPC_SYSCON->SYSMEMREMAP = 1; __DMB();
#ifdef __USE_CMSIS SystemInit(); #endif
// // Call the application's entry point. // __main() is the entry point for redlib based applications (which calls main()) // main() is the entry point for newlib based applications // if (__main) __main(); else main();
// // main() shouldn't return, but if it does, we'll just enter an infinite loop // while (1) { ; } }
|
|
|
|
|
Oct 21 2010, 12:52
|

Частый гость
 
Группа: Свой
Сообщений: 173
Регистрация: 30-11-05
Из: San Francisco
Пользователь №: 11 593

|
Цитата(Alekseeey @ Oct 21 2010, 15:12)  Вот код функции Reset_Handler из примера с моими изменениями: Если честно не совсем понял зачем это все в Reset_Handler. Он от бутлоадера или от прошиваемой проги? Какая у вас логика работы бутлоадера? Цитата(DpInRock @ Oct 21 2010, 15:38)  Вообще-то так и должно быть.
Как правильно (это мое имхо, но которое работает).
0. Компилируем программу и линковщику показываем реальные адреса. 1. Грузим программу с нужного адреса. 2. Копируем вектора, только если ремаповая область не совпадает с расположением программы (к примеру код находится SDRAM или FLASH). Т.е в этом случае копируем из области своей программы в область которая может содержать вектора и ремапится. 3. Далее запрещаем прерывания и JMP на начало своей программы: либо на реальное начало, либо на начальный адрес зоны векторов, которые ремапили (там одно и тоже будет - goto Startup).
Что характерно, не надо трогать стеки. Ибо стартап их настроит как вы в линкере укажите. А почему оно так должно быть и как починить? 0. Основная прога собрана с адреса 0x2000. RAM использует с 0x100000C0. 1. Верно, бутлоадер прощивает основную прогу во флеш по адресу 0x2000. 2. Копируем таблицу векторов. Т.е. 0xC0 байт c адреса 0x2000 в 0x10000000. 3. Ну перед джампом надо же сделать ремап, чтобы вектора из ОЗУ появились с адреса 0x0. И вот тут у меня сразу улетает куда-то в середину бутлоадера. А как это стеки трогать не надо? У Cortex M0 вершина стека хранится в самом начале векторов и проц после ресета сам ее оттуда берет. А т.к. мы скачем в основную прогу без ресета, а из своего бутлоадера, то надо самому правильно стек настроить. Стартап у кортексов стеки не настраивает.
|
|
|
|
|
Oct 21 2010, 12:58
|

Гуру
     
Группа: Участник
Сообщений: 2 254
Регистрация: 4-05-07
Из: Moscow
Пользователь №: 27 515

|
Reset - это место откуда программа стартует. Как бы по сигналу сброса. Как бы независимо. Но в реальности по сигналу сброса проц идет на собственный загрузчик и передает управление программе после ремапа. И тут якобы она стартует с 0. Делает вид,что после сброса как бы. Разумеется, можно написать даже процедуру, которая будет располагаться с 0. Токо следущими идут вектора прерываний. И если прерывания не используются - да ради бога. Можно. Против кортекса не попрешь. Извиняюсь. Но логика все равно остается. Не забывать прерывания убить. Ну и правильно джамп сделать. С переключением в режим супервизора. Я делаю Код void JMP(unsigned int addr) { //asm ("mov r0, addr \n"); asm ("SWI 0 \n"); } Вот так примерно. В том плане, что я стартую с нуля всегда после ремапа. Ибо так универсальнее, разумеется. (У меня все остальное - типа переключателя задач работает в супервизоре - выбрал за красивое название) НУ, еще контроллр внешней памяти не забыть настроить... У меня-то вектора в локальной памяти...
Сообщение отредактировал DpInRock - Oct 21 2010, 13:05
--------------------
On the road again (Canned Heat)
|
|
|
|
|
Oct 21 2010, 13:01
|
Участник

Группа: Участник
Сообщений: 32
Регистрация: 21-09-10
Пользователь №: 59 626

|
Цитата(zuy @ Oct 21 2010, 16:52)  Если честно не совсем понял зачем это все в Reset_Handler. Он от бутлоадера или от прошиваемой проги? Какая у вас логика работы бутлоадера? Логику работы бутлоадера я пока оставил в стороне - у меня не работает именно ремап. Я попытался взять работающий пример и сделать ремап векторов не трогая ничего другого. По идее все долно было работать без изменений. Но не работает.  Что-то делаю не правильно, но не знаю что. А вообще логика бутлоадера будет такой: лоадер в 0-й странице флеш, грузит программу в страницы 1..7, копирует ее вектора прерываний в ОЗУ и передает управление ей.
|
|
|
|
|
Oct 21 2010, 13:01
|

Частый гость
 
Группа: Свой
Сообщений: 173
Регистрация: 30-11-05
Из: San Francisco
Пользователь №: 11 593

|
Цитата(DpInRock @ Oct 21 2010, 15:54)  Reset - это место откуда программа стартует. Как бы по сигналу сброса. Как бы независимо. Но в реальности по сигналу сброса проц идет на собственный загрузчик и передает управление программе после ремапа. И тут якобы она стартует с 0. Делает вид,что после сброса как бы. Да, это понятно. Мой бут делает в общем тоже самое, что и встроенный, только ремапит вектора не из флеша, а из ОЗУ. Вроде нашел косяк. Забыл прерывания отключить до ремапа! Тогда еще вопрос. А барьеры синхронизации или памяти нужно после ремапа ставить или нет?
|
|
|
|
|
Oct 21 2010, 13:41
|
Участник

Группа: Участник
Сообщений: 32
Регистрация: 21-09-10
Пользователь №: 59 626

|
Цитата(zuy @ Oct 21 2010, 17:01)  Да, это понятно. Мой бут делает в общем тоже самое, что и встроенный, только ремапит вектора не из флеша, а из ОЗУ.
Вроде нашел косяк. Забыл прерывания отключить до ремапа!
Тогда еще вопрос. А барьеры синхронизации или памяти нужно после ремапа ставить или нет? Пожалуйста, опубликуйте работающий вариант процедуры ремапа. В usermanual lpc1114 написано на стр. 317: Vector table — If the program changes an entry in the vector table, and then enables the corresponding exception, use a DMB instruction between the operations. This ensures that if the exception is taken immediately after being enabled the processor uses the new exception vector. Судя по всему - надо.
|
|
|
|
|
Oct 21 2010, 17:28
|

Частый гость
 
Группа: Свой
Сообщений: 173
Регистрация: 30-11-05
Из: San Francisco
Пользователь №: 11 593

|
Цитата(Alekseeey @ Oct 21 2010, 16:41)  Пожалуйста, опубликуйте работающий вариант процедуры ремапа. Да вот что-то еще не прокатило, разбираюсь. Как будет рабочий вариант, отпишу
|
|
|
|
|
Oct 21 2010, 19:14
|

Частый гость
 
Группа: Свой
Сообщений: 173
Регистрация: 30-11-05
Из: San Francisco
Пользователь №: 11 593

|
Нет, все равно решительно не понимаю, что делает ремап в LPC1114. Вот простой код, который просто включает светодиод, и через некоторое время выключает: Код int main(void ) { unsigned long *dst, size, i; const unsigned long *src;
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<16) | (1<<6); // Enable IOCON GPIO LPC_GPIO1->DIR |= ( 1 << 8 ); // LED pin direction out LPC_GPIO1->DATA &= ~( 1 << 8 ); // LED ON
// Copy vectors table from 0x0 to RAM src = (unsigned long *)0; dst = (unsigned long *)0x10000000; size = 0xC0 >> 2; do { *dst++ = *src++; } while (--size);
// Pause, just to mention the LED state. i= 10000000; while( --i );
__disable_irq(); LPC_SYSCON->SYSMEMREMAP = 0x01; // remap to SRAM __ISB();
LPC_GPIO1->DATA |= ( 1 << 8 ); // LED OFF
while( 1 ); } Чтобы ремап не мешал работать, я копирую таблицу векторов из флеш в RAM. Если строка с ремапом присутствует то код не работает, если ее комментирую то все нормально. Но я же скопировал таблицу в RAM. Т.е. после ремапа для процессора вообще ничего не поменялось в начале адресного пространства! Кто-нибудь может объяснить что тут происходит?
|
|
|
|
|
Oct 21 2010, 20:30
|
Участник

Группа: Участник
Сообщений: 32
Регистрация: 21-09-10
Пользователь №: 59 626

|
Цитата(zuy @ Oct 21 2010, 23:14)  Нет, все равно решительно не понимаю, что делает ремап в LPC1114.
Кто-нибудь может объяснить что тут происходит? Обьяснить, к сожалению не могу, но могу от себя добавить, что когда я выполняю программу в отладчике по шагам, по ассемблерным коммандам, то при включенном ремапе происходит HardFault на инструкциях ветвления. Причем, в тестовой программе blinky это исключение возникает при попытке перехода на main();, но не происходит при переходе на SystemInit(); В памяти SystemInit расположена вверх по адресам от точки вызова, а main - вниз, не знаю, важно это или нет... Вот только что увеличил размер зарез. области до 0x1000 и скопировал туда 0x1000 байт флеш. Программа blinky дошла до main и попыталась начать работать. Прогресс. Да, проект blinky заработал. При включенном ремапе. После копирования в ОЗУ 0x1000 байт флеша. У меня нехорошие предчувствия по поводу ремапа... Интересная опечатка (?) есть в старых версиях user manual на lpc1114: на картинке карты памяти размер области векторов указан 0x0200 байт. И если я копирую 0x0200 байт, то программа работает...
|
|
|
|
|
Oct 21 2010, 20:43
|

Частый гость
 
Группа: Свой
Сообщений: 173
Регистрация: 30-11-05
Из: San Francisco
Пользователь №: 11 593

|
Цитата(Alekseeey @ Oct 21 2010, 23:09)  Обьяснить, к сожалению не могу, но могу от себя добавить, что когда я выполняю программу в отладчике по шагам, по ассемблерным коммандам, то при включенном ремапе происходит HardFault на инструкциях ветвления. Отладчик Keil ? Он для LPC1114 не совсем корректно работает. Тот пример что я привел в случае если ремап убрать, то вылетает в отладчике в HardFault, но работает отлично в железе. Цитата(Alekseeey @ Oct 21 2010, 23:30)  Интересная опечатка (?) есть в старых версиях user manual на lpc1114: на картинке карты памяти размер области векторов указан 0x0200 байт. И если я копирую 0x0200 байт, то программа работает... Рано я обрадовался. в 0х200 байт у меня вся тестовая прога. Получается я ее скопировал всю в ОЗУ. В реальном бутлоадере это не помогло :-(
|
|
|
|
|
Oct 21 2010, 21:09
|

Частый гость
 
Группа: Свой
Сообщений: 173
Регистрация: 30-11-05
Из: San Francisco
Пользователь №: 11 593

|
Цитата(rezident @ Oct 21 2010, 23:55)  Возникло предположение, что ремапу подвергается Flash кратно одному полному сектору размером 512 байт. Посмотрел в других кристаллах Cortex-M0 и Cortex-M3 - аналогично: либо 512 байт, либо 256 слов. Видимо бангалорские писатели даташитов что-то перемудрили  К сожалению, под рукой у меня нету ни LPC1114, ни отладчика, чтобы чем-то помочь в исследовании проблемы  Абсолютно верно. Я точно не проверял 512байт или какое другое значение, но факт в том, что действительно ремап отображает не таблицу векторов в 0хС0 байт, а больше. Я решил просто. Разместил код запуска основной проги в начале. Глянул какой максимальный адрес он занимает и копирую в ОЗУ все до этого адреса. После ремапа, получается этот же код и отображается из ОЗУ и проц продолжает работать. Далее я уже переписываю первые 0xc0 байт векторов из основной проги, и передаю ей управление через загрузку SP и PC. Все работает.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|