yanvasilij 0 21 декабря, 2016 Опубликовано 21 декабря, 2016 (изменено) · Жалоба Доброго времени суток! Вроде бы тривиальная задача, а вот однако застрял не могу понять, где ошибся. Проц - stm32f429. Суть такая "верхнее" приложение парсит hex-файл, выбрасывая из него все служебные данные, и данные не относящиеся к flash. Далее полученное подобие bin отправляется байт за байтом по последовательному порту в микроконтроллер. Микроконтроллер принимает, зашивает и переключается. Так вот после переключения ничего не происходит, проц зависает непонятно где. Прошивку принятой программы я делаю так: #define AVALIABLE_SECTORS_NUM 17 /**< @brief Общее количество доступных мне секторов */ #define USER_APP_START_ADR 0x08020000 /**< @brief Адрес куда шить программу */ /** Сектора, которые мне доступны */ static const u16 sectors [AVALIABLE_SECTORS_NUM] = { FLASH_Sector_5, FLASH_Sector_6, FLASH_Sector_7, FLASH_Sector_8, FLASH_Sector_9, FLASH_Sector_10, FLASH_Sector_11, FLASH_Sector_12, FLASH_Sector_13, FLASH_Sector_14, FLASH_Sector_15, FLASH_Sector_16, FLASH_Sector_17, FLASH_Sector_18, FLASH_Sector_19, FLASH_Sector_20, FLASH_Sector_21 }; /** Тут лежит принятая прошивка (массив в SDRAM) */ static u8 __attribute__((section ("._sdram"))) userApp[MAX_BIN_FILE_LEN]; /** Это счетчик принятых байт */ static u32 byteCount = 0; void programmUserApp (void) { u32 numOfPages = byteCount / PAGE_LEN; if (byteCount % PAGE_LEN) numOfPages++; FLASH_Unlock(); FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR|FLASH_FLAG_PGSERR); /** Стираю необходимые мне сектора */ for (u32 i = 0; i < numOfPages; i++) { if (FLASH_EraseSector(sectors[i], VoltageRange_3) != FLASH_COMPLETE) { FLASH_Lock(); while (1); /* Стопор на всякий случай */ } } /** Далее шью по 4 байта */ u32 * word = (u32*)userApp; u32 wordCount = byteCount/4; if (byteCount%4) wordCount++; u32 adr = USER_APP_START_ADR; for (u32 i = 0; i < wordCount; i++) { if (FLASH_ProgramWord(adr, *(word++)) != FLASH_COMPLETE) { FLASH_Lock(); while (1); /* Стопор на всякий случай */ } adr += 4; } FLASH_Lock(); } Далее, чтобы удостовериться, что я зашил, то что хотел, я считываю и вывожу в последовательный порт данные, которые оказались во flash в результате моих манипуляций: void showProgram (void) { u8 * p = (u8*) USER_APP_START_ADR; printf ("\r\n"); for (u32 i = 0, j = 0; i < byteCount; i++, j++) { if ( (j>0) && ((j%16) == 0) ) printf ("\r\n"); printf ("%02X", p[i]); } printf ("\r\n"); printf ("End\r\n"); } Переключаю программу вот так: typedef void(*VoidFunction)(void); void jumpToUserApp (void) { NVIC_SetVectorTable(NVIC_VectTab_FLASH, (USER_APP_START_ADR & (~(0x08000000)))); u32 jumpAddress = *(__IO uint32_t*) (USER_APP_START_ADR + 4); VoidFunction jumpToApp = (VoidFunction) jumpAddress; __set_MSP(*(__IO uint32_t*) USER_APP_START_ADR); jumpToApp(); } Так вот, после считыания я вижу, что зашилось именно то, что лежит в hex-файле в полях данных. То есть данные в hex и во flash совпадают (за вычетом служебных данных). Я не могу понять, что я упустил. Есть у кого соображения, поделитесь если не трудно? Изменено 29 ноября, 2022 пользователем haker_fox Уточнил название темы, добавил теги, переместил в нужный раздел. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kabdim 0 21 декабря, 2016 Опубликовано 21 декабря, 2016 · Жалоба Дебаг в ассемблере? Прошивка-то гарантированно рабочая? Если отладчиком залить по нужным адресам, а потом отладчиком установить msp и pc работать будет? Запретов прерывания и отключения использованной переферии нигде не видно, может в основной прошивке оно сразу в обработчик прерывания улетает? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
yanvasilij 0 21 декабря, 2016 Опубликовано 21 декабря, 2016 · Жалоба Дебаг в ассемблере? Прошивка-то гарантированно рабочая? Если отладчиком залить по нужным адресам, а потом отладчиком установить msp и pc работать будет? Запретов прерывания и отключения использованной переферии нигде не видно, может в основной прошивке оно сразу в обработчик прерывания улетает? Ничего, если я проверю работоспособность прошивки следующим образом. В линкер файле уберу смещение: было: ... MEMORY { FLASH (rx) : ORIGIN = 0x08020000, LENGTH = 1024K ... } ... стало: ... MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K ... } ... Компилирую без смещения, зашиваю - работает. Такая проверка достаточна или непременно нужно отладчиком менять указатели? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kabdim 0 21 декабря, 2016 Опубликовано 21 декабря, 2016 · Жалоба Это не проверка на 100%, соответственно уверенности в том что прошивка работает со смешением нет. По поводу прерываний в бутлоадере - как оно у вас сделано? Всё таки просто пройдитесь в режиме асемблера отладчиком - сразу станет понятно что происходит с чипом. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
x893 55 21 декабря, 2016 Опубликовано 21 декабря, 2016 · Жалоба а отладчиком посмотреть ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
amiller 2 22 декабря, 2016 Опубликовано 22 декабря, 2016 · Жалоба Может Вы периферию успеваете в отладчике настроить? Или улетаете в прерывание в процессе переключения? Вообще есть правило, которое я считаю хорошим: При старте bootloadera самым первым делом проверять наличие адекватной прошивки по ранее записанному ключу. Если ключ есть, то переключаемся в программу пользователя, ключа нет - передаем управление загрузчику. Соответственно после прошивки записываем ключ и перегружаемся. А для перехода в режим загрузчика стираем ключ и перегружаемся. Ну и если программа пользователя виснет, нужно предусмотреть принудительный переход в режим загрузчика. Я для этого использую заглушку с перемычкой на разъёме JTAG(SWD). Проинициализировать пару выводов, опросить, а потом вернуть их в исходное состояние несложно. По коду переключения: Вы сначала устанавливаете начало таблицы векторов, а потом делаете переход в программу пользователя. Есть подозрение, что в начале выполнения программы пользователя на уровне стартапа начало таблицы векторов переопределяется. Происходит что-то вроде этого: SCB->VTOR = (int32u)&__vector_table; // Vector Table Relocation И если Вы не озаботились установить смещение и для этой константы где-то в файле линкера, то может быть установлена таблица прерываний от загрузчика. Ну и если Вы взялись за написание загрузчика, то в самом коде переключения надо обходится без библиотек сторонних типа CMSYS. Нельзя быть уверенным, что в процессе инициализации эти библиотеки что-нибудь Вам не настроят. А потом будете ловить непонятные глюки с периферией в программе пользователя. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
KnightIgor 2 22 декабря, 2016 Опубликовано 22 декабря, 2016 (изменено) · Жалоба Или улетаете в прерывание в процессе переключения? Присоединяюсь. Надо бы запретить прерывания. P.S. Глянул, как у меня с этим. Такие строчки перед переходом на новую прошивку: Deinit_Peripherals(); SysTick->CTRL &= ~(SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk); Под Deinit_Peripherals(); можно развернуться, насколько собственная фантазия позволит. А вот убиение SysTick было просто необходимо. Изменено 22 декабря, 2016 пользователем KnightIgor Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Aaron 1 23 декабря, 2016 Опубликовано 23 декабря, 2016 · Жалоба __disable_irq(); .... __set_MSP(*(__IO uint32_t*) USER_APP_START_ADR); __set_CONTROL(0x00000000); // switch to "main" stack pointer - ну по идее это должно вообще лежать где-нибудь в __Init_Data() jumpToApp(); 1. Отключать прерывания обязательно - мало ли как вы попали в загрузчик ;) 2. То же самое касается стека. Можно ещё чуток пофантазировать. Например, передача управления клоков, настройка PLL. Может, у вас и в загрузчике, и в боевой программе: а) отключается PLL; б) настраивается PLL; в) клок переключается на PLL; тогда после возврата от в) к а) процессор тупо остановится :) В общем, посмотрите ещё в сторону инициализации клоков! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
yanvasilij 0 23 декабря, 2016 Опубликовано 23 декабря, 2016 · Жалоба ...Всё таки просто пройдитесь в режиме асемблера отладчиком - сразу станет понятно что происходит с чипом. Вообщем Вы правильно настаивали, когда заставляли запустить из под отладчика. Запустил выяснил, что со смещением программа не стартует. После этого начал копать глубже. SCB->VTOR = (int32u)&__vector_table; // Vector Table Relocation Вы попали в точку! В SystemInit вторичной программы это действительно было. __disable_irq(); .... __set_MSP(*(__IO uint32_t*) USER_APP_START_ADR); __set_CONTROL(0x00000000); // switch to "main" stack pointer - ну по идее это должно вообще лежать где-нибудь в __Init_Data() jumpToApp(); Спасибо за совет, внял ему. Ну и по поводу отключения прерываний, согласен со всеми. Сейчас я их предварительно отключаю. Вообще удалось запустить бутлоадер. Ошибок оказалось много, это во-первых ошибка в парсере hex-файла (тот который отправляет прошивку в микроконтроллер), во-вторых ошибка с неверным переключением смещения таблицы векторов во вторичной программе (про это говорил amiller), ну и в третьих повторная инициализация pll, про которую сказал Aaron. Сейчас все работает, спасибо большое всем за помощь! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться