Cosmojam 0 15 августа, 2013 Опубликовано 15 августа, 2013 · Жалоба Не получается запустить приложение из загрузчика. Пример из 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. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Axel 1 15 августа, 2013 Опубликовано 15 августа, 2013 · Жалоба Поделитесь у кого есть реально рабочий код запуска приложения из загрузчика на этом процессоре с gcc. Делюсь: 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 } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Артём__ 0 15 августа, 2013 Опубликовано 15 августа, 2013 · Жалоба Не получается запустить приложение из загрузчика. Пример из 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(); вызывает сброс в lockup и так по кругу. На следующем старте источник сброса SYSRESET и LOCKUP в RSID. Видимо вы что-то не то запускаете и нет обработчика HardFault и получаете переход в lockup-state. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Cosmojam 0 15 августа, 2013 Опубликовано 15 августа, 2013 · Жалоба Спасибо за код и подсказку. Буду внимательнее смотреть корректность приложения. Зачем тут ассемблер применять? Так было в аппноуте когда делал это на LPC1768. Через указатель на функцию тогда не получалось, видимо по другим причинам, но решив их оставил как было в аппноуте ибо нефик трогать то что работает :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Fedor 0 16 августа, 2013 Опубликовано 16 августа, 2013 · Жалоба Попробуйте обявить эту функцию с __attribute__((naked)) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Cosmojam 0 16 августа, 2013 Опубликовано 16 августа, 2013 · Жалоба Попробуйте обявить эту функцию с __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() в периферийной библиотеке. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
slavka012 0 30 сентября, 2013 Опубликовано 30 сентября, 2013 · Жалоба Делюсь: 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 по сравнению с запуском приложения без бутлоадера. Ассемблерный вариант работает правильно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
yanvasilij 0 6 ноября, 2013 Опубликовано 6 ноября, 2013 (изменено) · Жалоба У меня схожая проблема. При переключении из bootloadera в рабочую программу в рабочей программе не стартует Freertos. То есть все, что до запуска планировщика работает, а как только доходит до запуска планировщика все рушится. FreeRtos присутствует и в bootloadere и в рабочей программе. Отладить вообще не представляю как, ибо рабочая программа загружается по с tftp-сервера, только по логам в уарте сужу, что происходит. ъ /** * @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); } ... Буду признателен за помощь. Изменено 6 ноября, 2013 пользователем IgorKossak [codebox] для длинного кода, [code] - для короткого!!! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Cosmojam 0 6 ноября, 2013 Опубликовано 6 ноября, 2013 · Жалоба Попробуйте отключить systick перед запуском приложения. В начале функции switchProgram(): SysTick->CTRL &= ~((uint32_t)(1<<0)); // отключает таймер SysTick->CTRL &= ~((uint32_t)(1<<1)); // отключает прерывание SysTick->CTRL &= ~((uint32_t)(1<<16)); // сбрасывает флаг Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Bass 0 6 ноября, 2013 Опубликовано 6 ноября, 2013 · Жалоба В таблице векторов прерываний по нулевому смещению присутствует адрес стека приложения? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
yanvasilij 0 7 ноября, 2013 Опубликовано 7 ноября, 2013 · Жалоба Cosmojam Отключение systick не помогло. Bass Не совсем понял Ваш вопрос: речь идет о таблице векторов бутлоадера или рабочей программы? Я выяснил, что в рабочей программе перестает работать FreeRtos, когда я подключаю к проекту бутлоадера драйвер etherneta EMAC_LPC177x_8x.c. Исключаю его из компиляции - все работает, подключает ось в рабочей программе не стартует. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
yanvasilij 0 7 ноября, 2013 Опубликовано 7 ноября, 2013 (изменено) · Жалоба Я понял в чем проблема. Все дело в функции systemInit, которая вызывается у меня в начале всех программ. Ошибка конечно глупейшая, я не углядел, что в ней тоже инициализируется регистр VTOR: 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, либо не вызывать второй раз ее, раз уж она в буте используется. Изменено 7 ноября, 2013 пользователем IgorKossak [codebox] для длинного кода, [code] - для короткого!!! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Cosmojam 0 7 ноября, 2013 Опубликовано 7 ноября, 2013 · Жалоба Выходит, что вектора надо ремапить либо во второй программе, после systemInit, либо не вызывать второй раз ее, раз уж она в буте используется. Ремапить в загрузчике и приложении можно так: SCB->VTOR = (unsigned long)&g_pfnVectors & 0x3FFFFF80; Сразу после вызова SystemInit(). Так указывается адрес таблицы векторов всегда на фактический её адрес независимо от абсолютного адреса куда линкер её положил. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
yanvasilij 0 7 ноября, 2013 Опубликовано 7 ноября, 2013 · Жалоба Cosmojam Где определен указатель g_pfnVectors? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Cosmojam 0 7 ноября, 2013 Опубликовано 7 ноября, 2013 · Жалоба Cosmojam Где определен указатель g_pfnVectors? В стартап файле из любого примера NXP. Там таблица векторов определена в этом массиве в виде указателей на функции. Правда это в примерах от NXP под GNU-тые средства разработки. Под другие может иначе сделано. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться