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

 
 
 
Reply to this topicStart new topic
> Самописный бутлоадер STM32
yanvasiij
сообщение Dec 21 2016, 14:10
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 321
Регистрация: 23-12-11
Из: Уфа
Пользователь №: 69 041



Доброго времени суток!

Вроде бы тривиальная задача, а вот однако застрял не могу понять, где ошибся. Проц - stm32f429. Суть такая "верхнее" приложение парсит hex-файл, выбрасывая из него все служебные данные, и данные не относящиеся к flash. Далее полученное подобие bin отправляется байт за байтом по последовательному порту в микроконтроллер. Микроконтроллер принимает, зашивает и переключается. Так вот после переключения ничего не происходит, проц зависает непонятно где.

Прошивку принятой программы я делаю так:

CODE


#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 в результате моих манипуляций:

CODE


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");
}


Переключаю программу вот так:

CODE

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 совпадают (за вычетом служебных данных). Я не могу понять, что я упустил. Есть у кого соображения, поделитесь если не трудно?
Go to the top of the page
 
+Quote Post
Kabdim
сообщение Dec 21 2016, 14:22
Сообщение #2


Знающий
****

Группа: Свой
Сообщений: 558
Регистрация: 26-11-14
Из: Зеленоград
Пользователь №: 83 842



Дебаг в ассемблере?
Прошивка-то гарантированно рабочая? Если отладчиком залить по нужным адресам, а потом отладчиком установить msp и pc работать будет? Запретов прерывания и отключения использованной переферии нигде не видно, может в основной прошивке оно сразу в обработчик прерывания улетает?
Go to the top of the page
 
+Quote Post
yanvasiij
сообщение Dec 21 2016, 14:32
Сообщение #3


Местный
***

Группа: Свой
Сообщений: 321
Регистрация: 23-12-11
Из: Уфа
Пользователь №: 69 041



Цитата(Kabdim @ Dec 21 2016, 19:22) *
Дебаг в ассемблере?
Прошивка-то гарантированно рабочая? Если отладчиком залить по нужным адресам, а потом отладчиком установить msp и pc работать будет? Запретов прерывания и отключения использованной переферии нигде не видно, может в основной прошивке оно сразу в обработчик прерывания улетает?


Ничего, если я проверю работоспособность прошивки следующим образом. В линкер файле уберу смещение:

было:

Код
...
MEMORY
{
  FLASH (rx)      : ORIGIN = 0x08020000, LENGTH = 1024K
...
}
...


стало:

Код
...
MEMORY
{
  FLASH (rx)      : ORIGIN = 0x08000000, LENGTH = 1024K
...
}
...


Компилирую без смещения, зашиваю - работает. Такая проверка достаточна или непременно нужно отладчиком менять указатели?
Go to the top of the page
 
+Quote Post
Kabdim
сообщение Dec 21 2016, 15:00
Сообщение #4


Знающий
****

Группа: Свой
Сообщений: 558
Регистрация: 26-11-14
Из: Зеленоград
Пользователь №: 83 842



Это не проверка на 100%, соответственно уверенности в том что прошивка работает со смешением нет. По поводу прерываний в бутлоадере - как оно у вас сделано? Всё таки просто пройдитесь в режиме асемблера отладчиком - сразу станет понятно что происходит с чипом.
Go to the top of the page
 
+Quote Post
x893
сообщение Dec 21 2016, 15:32
Сообщение #5


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

Группа: Свой
Сообщений: 1 333
Регистрация: 27-10-08
Из: Планета Земля
Пользователь №: 41 226



а отладчиком посмотреть ?
Go to the top of the page
 
+Quote Post
amiller
сообщение Dec 22 2016, 04:04
Сообщение #6


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

Группа: Участник
Сообщений: 176
Регистрация: 20-02-14
Из: Томск
Пользователь №: 80 612



Может Вы периферию успеваете в отладчике настроить? Или улетаете в прерывание в процессе переключения?
Вообще есть правило, которое я считаю хорошим:
При старте bootloadera самым первым делом проверять наличие адекватной прошивки по ранее записанному ключу.
Если ключ есть, то переключаемся в программу пользователя, ключа нет - передаем управление загрузчику.
Соответственно после прошивки записываем ключ и перегружаемся.
А для перехода в режим загрузчика стираем ключ и перегружаемся.
Ну и если программа пользователя виснет, нужно предусмотреть принудительный переход в режим загрузчика.
Я для этого использую заглушку с перемычкой на разъёме JTAG(SWD). Проинициализировать пару выводов, опросить, а потом вернуть их в исходное состояние несложно.

По коду переключения:
Вы сначала устанавливаете начало таблицы векторов, а потом делаете переход в программу пользователя.
Есть подозрение, что в начале выполнения программы пользователя на уровне стартапа начало таблицы векторов переопределяется.
Происходит что-то вроде этого:
SCB->VTOR = (int32u)&__vector_table; // Vector Table Relocation
И если Вы не озаботились установить смещение и для этой константы где-то в файле линкера, то может быть установлена таблица прерываний от загрузчика.

Ну и если Вы взялись за написание загрузчика, то в самом коде переключения надо обходится без библиотек сторонних типа CMSYS.
Нельзя быть уверенным, что в процессе инициализации эти библиотеки что-нибудь Вам не настроят. А потом будете ловить непонятные глюки с периферией в программе пользователя.
Go to the top of the page
 
+Quote Post
KnightIgor
сообщение Dec 22 2016, 10:31
Сообщение #7


Знающий
****

Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725



Цитата(amiller @ Dec 22 2016, 06:04) *
Или улетаете в прерывание в процессе переключения?

Присоединяюсь. Надо бы запретить прерывания.

P.S. Глянул, как у меня с этим. Такие строчки перед переходом на новую прошивку:
Код
        Deinit_Peripherals();
        SysTick->CTRL &= ~(SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk);

Под Deinit_Peripherals(); можно развернуться, насколько собственная фантазия позволит. А вот убиение SysTick было просто необходимо.

Сообщение отредактировал KnightIgor - Dec 22 2016, 13:06
Go to the top of the page
 
+Quote Post
Aaron
сообщение Dec 23 2016, 12:49
Сообщение #8


Местный
***

Группа: Свой
Сообщений: 243
Регистрация: 5-10-06
Из: Зеленоград
Пользователь №: 21 007



Код
__disable_irq();
....
__set_MSP(*(__IO uint32_t*) USER_APP_START_ADR);
__set_CONTROL(0x00000000); // switch to "main" stack pointer - ну по идее это должно вообще лежать где-нибудь в __Init_Data()
jumpToApp();

1. Отключать прерывания обязательно - мало ли как вы попали в загрузчик wink.gif
2. То же самое касается стека.
Можно ещё чуток пофантазировать. Например, передача управления клоков, настройка PLL. Может, у вас и в загрузчике, и в боевой программе:
а) отключается PLL;
б) настраивается PLL;
в) клок переключается на PLL;
тогда после возврата от в) к а) процессор тупо остановится sm.gif В общем, посмотрите ещё в сторону инициализации клоков!
Go to the top of the page
 
+Quote Post
yanvasiij
сообщение Dec 23 2016, 17:56
Сообщение #9


Местный
***

Группа: Свой
Сообщений: 321
Регистрация: 23-12-11
Из: Уфа
Пользователь №: 69 041



Цитата(Kabdim @ Dec 21 2016, 20:00) *
...Всё таки просто пройдитесь в режиме асемблера отладчиком - сразу станет понятно что происходит с чипом.


Вообщем Вы правильно настаивали, когда заставляли запустить из под отладчика. Запустил выяснил, что со смещением программа не стартует. После этого начал копать глубже.

Цитата(amiller @ Dec 22 2016, 09:04) *
SCB->VTOR = (int32u)&__vector_table; // Vector Table Relocation


Вы попали в точку! В SystemInit вторичной программы это действительно было.

Цитата(Aaron @ Dec 23 2016, 17:49) *
Код
__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. Сейчас все работает, спасибо большое всем за помощь!
Go to the top of the page
 
+Quote Post

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

 


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


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