|
[Решено] LPC1788 bootloader переход на адрес приложения, приводит к lockup |
|
|
|
Aug 15 2013, 12:11
|
Местный
  
Группа: Свой
Сообщений: 311
Регистрация: 12-01-11
Из: Калининград (Koenigsberg)
Пользователь №: 62 182

|
Не получается запустить приложение из загрузчика. Пример из AN10866 работает на LPC1768, но на LPC1788 Код static void boot(uint32_t a) { __asm volatile ( "LDR SP, [R0]\n" "LDR PC, [R0, #4]\n" ); } вызывает сброс в lockup и так по кругу. На следующем старте источник сброса SYSRESET и LOCKUP в RSID. Посмотреть отладчиком что там происходит крайне затруднительно по причине его тормознутости и глючности (китайский j-link, кое-как с openocd рабоает и вообще никак с фирменной софтиной) Код __disable_irq(); __disable_fault_irq();
delay_loop(3000000u); SCB->VTOR = (start_address & 0x1FFFFF80); __asm volatile ( "dmb\n" "dsb\n" "isb\n" ); boot(start_address); Приложение записано с помощью IAP и судя по содержимому памяти записано верно. На LPC1768 помню приходилось перед модификацией PC переключаться на встроенный RC генератор и отключать PLL Тут это тоже пробовал - не помогает, либо я не правильно читаю даташит. Поделитесь у кого есть реально рабочий код запуска приложения из загрузчика на этом процессоре с gcc.
--------------------
typedef enum { no, yes, maybe } bool; | блог тут
|
|
|
|
|
Aug 15 2013, 12:44
|
Местный
  
Группа: Свой
Сообщений: 480
Регистрация: 21-11-04
Пользователь №: 1 188

|
Цитата(Cosmojam @ Aug 15 2013, 15:11)  Поделитесь у кого есть реально рабочий код запуска приложения из загрузчика на этом процессоре с gcc. Делюсь: CODE typedef void (*pFunction)(uint32_t app_start);
void JumpToApp (uint32_t app_start) { pFunction jump_to_app = (pFunction)(*(volatile uint32_t *) (app_start + 4));
LPC_SC->CCLKSEL = 0x01; // set sysclk (12MHz) as clock source LPC_SC->PLL0CON = 0; // disable PLL LPC_SC->PLL0FEED = 0xAA; LPC_SC->PLL0FEED = 0x55;
SCB->VTOR = (uint32_t)app_start; // Change the Vector Table to the APP_CODE_START __ASM volatile ("MSR psp, %0" : : "r" (*(volatile uint32_t *)app_start)); // Load new stack pointer address jump_to_app(app_start); // Jump to application code }
|
|
|
|
|
Aug 15 2013, 12:55
|
Гуру
     
Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322

|
Цитата(Cosmojam @ Aug 15 2013, 15:11)  Не получается запустить приложение из загрузчика. Пример из AN10866 работает на LPC1768, но на LPC1788 Код static void boot(uint32_t a) { __asm volatile ( "LDR SP, [R0]\n" "LDR PC, [R0, #4]\n" ); } Зачем тут ассемблер применять? Код typedef void (*IsrHandler_t) (void);
if (CrcOk()) { __set_MSP(*(uint32_t *)APPLICATION_MSP_ADDRESS); IsrHandler_t application_reset_handler=(IsrHandler_t)(*(uint32_t *)APPLICATION_RESET_ISR_ADDRESS); goto *application_reset_handler; } else NVIC_SystemReset(); Цитата(Cosmojam @ Aug 15 2013, 15:11)  вызывает сброс в lockup и так по кругу. На следующем старте источник сброса SYSRESET и LOCKUP в RSID. Видимо вы что-то не то запускаете и нет обработчика HardFault и получаете переход в lockup-state.
|
|
|
|
|
Aug 15 2013, 18:02
|
Местный
  
Группа: Свой
Сообщений: 311
Регистрация: 12-01-11
Из: Калининград (Koenigsberg)
Пользователь №: 62 182

|
Спасибо за код и подсказку. Буду внимательнее смотреть корректность приложения. Цитата(_Артём_ @ Aug 15 2013, 15:55)  Зачем тут ассемблер применять? Так было в аппноуте когда делал это на LPC1768. Через указатель на функцию тогда не получалось, видимо по другим причинам, но решив их оставил как было в аппноуте ибо нефик трогать то что работает
--------------------
typedef enum { no, yes, maybe } bool; | блог тут
|
|
|
|
|
Aug 16 2013, 08:29
|
Участник

Группа: Участник
Сообщений: 73
Регистрация: 26-10-05
Пользователь №: 10 125

|
Попробуйте обявить эту функцию с __attribute__((naked))
|
|
|
|
|
Aug 16 2013, 09:09
|
Местный
  
Группа: Свой
Сообщений: 311
Регистрация: 12-01-11
Из: Калининград (Koenigsberg)
Пользователь №: 62 182

|
Цитата(Fedor @ Aug 16 2013, 11:29)  Попробуйте обявить эту функцию с __attribute__((naked)) Уже без надобности. Разобрался. Похоже это было из-за прерываний, вставших в очередь. Помогло явное отключение всех прерываний и очистка очереди перед переходом Код NVIC->ICER[0] = 0xFFFFFFFF; NVIC->ICER[1] = 0x00000001; /* Clear all pending interrupts */ NVIC->ICPR[0] = 0xFFFFFFFF; NVIC->ICPR[1] = 0x00000001; /* Clear all interrupt priority */ uint8_t tmp = 0; for (tmp = 0; tmp < 32u; tmp++) { NVIC->IP[tmp] = 0x00; } Функция NVIC_DeInit() в периферийной библиотеке.
--------------------
typedef enum { no, yes, maybe } bool; | блог тут
|
|
|
|
|
Sep 30 2013, 17:17
|
self made
   
Группа: Свой
Сообщений: 855
Регистрация: 7-03-09
Из: Toronto, Canada
Пользователь №: 45 795

|
Цитата(Axel @ Aug 15 2013, 07:44)  Делюсь: CODE typedef void (*pFunction)(uint32_t app_start);
void JumpToApp (uint32_t app_start) { pFunction jump_to_app = (pFunction)(*(volatile uint32_t *) (app_start + 4));
LPC_SC->CCLKSEL = 0x01; // set sysclk (12MHz) as clock source LPC_SC->PLL0CON = 0; // disable PLL LPC_SC->PLL0FEED = 0xAA; LPC_SC->PLL0FEED = 0x55;
SCB->VTOR = (uint32_t)app_start; // Change the Vector Table to the APP_CODE_START __ASM volatile ("MSR psp, %0" : : "r" (*(volatile uint32_t *)app_start)); // Load new stack pointer address jump_to_app(app_start); // Jump to application code }
Этот метод не работает, точнее работает неправильно. При заходе в main() стэк оказывается сдвинут на 0x680 по сравнению с запуском приложения без бутлоадера. Ассемблерный вариант работает правильно.
|
|
|
|
|
Nov 6 2013, 07:38
|
Местный
  
Группа: Свой
Сообщений: 321
Регистрация: 23-12-11
Из: Уфа
Пользователь №: 69 041

|
У меня схожая проблема. При переключении из bootloadera в рабочую программу в рабочей программе не стартует Freertos. То есть все, что до запуска планировщика работает, а как только доходит до запуска планировщика все рушится. FreeRtos присутствует и в bootloadere и в рабочей программе. Отладить вообще не представляю как, ибо рабочая программа загружается по с tftp-сервера, только по логам в уарте сужу, что происходит. CODE ъ /** * @brief Переключиться в программу * * @param address адрес где расположенна программа * */ __asm void boot_jump( uint32_t address ) { LDR SP, [R0] ;Load new stack pointer address LDR PC, [R0, #4] ;Load new program counter address }
/** * @brief переключить программу * * @param address адрес, куда переключаться */ void switchProgram (uint32_t address) { NVIC->ICER[0] = 0xFFFFFFFF; NVIC->ICER[1] = 0x00000001; /* Clear all pending interrupts */ NVIC->ICPR[0] = 0xFFFFFFFF; NVIC->ICPR[1] = 0x00000001; /* Clear all interrupt priority */ uint8_t tmp = 0; for (tmp = 0; tmp < 32u; tmp++) { NVIC->IP[tmp] = 0x00; } SCB->VTOR = address; boot_jump(address); } Вот вырезка из места, где все это вызывается: Код ... else if(memcmp("switch\r", str, strlen("switch\r")) ==0 ) { taskEXIT_CRITICAL(); vTaskEndScheduler(); switchProgram(0x10000); } ... Буду признателен за помощь.
Сообщение отредактировал IgorKossak - Nov 6 2013, 18:44
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
|
|
|
|
|
Nov 6 2013, 17:10
|
Местный
  
Группа: Свой
Сообщений: 311
Регистрация: 12-01-11
Из: Калининград (Koenigsberg)
Пользователь №: 62 182

|
Попробуйте отключить systick перед запуском приложения. В начале функции switchProgram(): Код SysTick->CTRL &= ~((uint32_t)(1<<0)); // отключает таймер SysTick->CTRL &= ~((uint32_t)(1<<1)); // отключает прерывание SysTick->CTRL &= ~((uint32_t)(1<<16)); // сбрасывает флаг
--------------------
typedef enum { no, yes, maybe } bool; | блог тут
|
|
|
|
|
Nov 7 2013, 07:56
|
Местный
  
Группа: Свой
Сообщений: 321
Регистрация: 23-12-11
Из: Уфа
Пользователь №: 69 041

|
Я понял в чем проблема. Все дело в функции systemInit, которая вызывается у меня в начале всех программ. Ошибка конечно глупейшая, я не углядел, что в ней тоже инициализируется регистр VTOR: CODE void SystemInit (void) { #if (CLOCK_SETUP) /* Clock Setup */ LPC_SC->SCS = SCS_Val; if (SCS_Val & (1 << 5)) { /* If Main Oscillator is enabled */ while ((LPC_SC->SCS & (1<<6)) == 0);/* Wait for Oscillator to be ready */ }
LPC_SC->CLKSRCSEL = CLKSRCSEL_Val; /* Select Clock Source for sysclk/PLL0*/
#if (PLL0_SETUP) LPC_SC->PLL0CFG = PLL0CFG_Val; LPC_SC->PLL0CON = 0x01; /* PLL0 Enable */ LPC_SC->PLL0FEED = 0xAA; LPC_SC->PLL0FEED = 0x55; while (!(LPC_SC->PLL0STAT & (1<<10)));/* Wait for PLOCK0 */ #endif
#if (PLL1_SETUP) LPC_SC->PLL1CFG = PLL1CFG_Val; LPC_SC->PLL1CON = 0x01; /* PLL1 Enable */ LPC_SC->PLL1FEED = 0xAA; LPC_SC->PLL1FEED = 0x55; while (!(LPC_SC->PLL1STAT & (1<<10)));/* Wait for PLOCK1 */ #endif
LPC_SC->CCLKSEL = CCLKSEL_Val; /* Setup Clock Divider */ LPC_SC->USBCLKSEL = USBCLKSEL_Val; /* Setup USB Clock Divider */ LPC_SC->EMCCLKSEL = EMCCLKSEL_Val; /* EMC Clock Selection */ LPC_SC->PCLKSEL = PCLKSEL_Val; /* Peripheral Clock Selection */ LPC_SC->PCONP = PCONP_Val; /* Power Control for Peripherals */ LPC_SC->CLKOUTCFG = CLKOUTCFG_Val; /* Clock Output Configuration */ #endif
#if (FLASH_SETUP == 1) /* Flash Accelerator Setup */ LPC_SC->FLASHCFG = FLASHCFG_Val|0x03A; #endif
#ifdef __RAM_MODE__ SCB->VTOR = 0x10000000 & 0x3FFFFF80; /* <<< ВОТ ЗДЕСЬ ОН ИНИЦИАЛИЗИРУЕТСЯ ПОВТОРНО */ #else SCB->VTOR = 0x00000000 & 0x3FFFFF80; #endif
} Выходит, что вектора надо ремапить либо во второй программе, после systemInit, либо не вызывать второй раз ее, раз уж она в буте используется.
Сообщение отредактировал IgorKossak - Nov 7 2013, 08:14
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
|
|
|
|
|
Nov 7 2013, 09:08
|
Местный
  
Группа: Свой
Сообщений: 311
Регистрация: 12-01-11
Из: Калининград (Koenigsberg)
Пользователь №: 62 182

|
Цитата(yanvasiij @ Nov 7 2013, 10:56)  Выходит, что вектора надо ремапить либо во второй программе, после systemInit, либо не вызывать второй раз ее, раз уж она в буте используется. Ремапить в загрузчике и приложении можно так: SCB->VTOR = (unsigned long)&g_pfnVectors & 0x3FFFFF80; Сразу после вызова SystemInit(). Так указывается адрес таблицы векторов всегда на фактический её адрес независимо от абсолютного адреса куда линкер её положил.
--------------------
typedef enum { no, yes, maybe } bool; | блог тут
|
|
|
|
|
Nov 7 2013, 17:02
|
Местный
  
Группа: Свой
Сообщений: 311
Регистрация: 12-01-11
Из: Калининград (Koenigsberg)
Пользователь №: 62 182

|
Цитата(yanvasiij @ Nov 7 2013, 13:02)  Cosmojam Где определен указатель g_pfnVectors? В стартап файле из любого примера NXP. Там таблица векторов определена в этом массиве в виде указателей на функции. Правда это в примерах от NXP под GNU-тые средства разработки. Под другие может иначе сделано.
--------------------
typedef enum { no, yes, maybe } bool; | блог тут
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|