0 / 0 / 0
Регистрация: 30.12.2015
Сообщений: 74

[Решено] bootloader, jump to application, hardfault

08.08.2017, 14:09. Показов 17682. Ответов 18
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго времени суток.
Знаю, что подобное уже обсуждалось, однако то, что я вычитал, мне не помогло :(
Есть stm32l151CBT6, там стоит загрузчик и, когда необходимо, прыгает в основную прошивку. Всё работало исправно, пока я не расширил функционал. Теперь же после прыжка попадаю в HordFault.
Code
1
2
3
4
5
__disable_interrupt();
JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
Jump_To_Application = (pFunction) JumpAddress;
__set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
Jump_To_Application();
Стандартный кусок. Среда - IAR 6.5. Увеличивал stack и heap. Даже когда после __set_MSP на стек не ругается, всё равно выпадает в ошибку.
Гуглил что-то про регистры, характерные для данного ядра, которые могут подсказать причину ошибки, но понимания не достиг. В какую сторону лучше копать?
Думаю, код основной прошивки тут не влияет.
P.S. флаги FORCED и IBUSERR выставлены.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
08.08.2017, 14:09
Ответы с готовыми решениями:

stm32f0 bootloader - HardFault после __enable_irq
Пишу свой boottooder для контроллера stm32f030rc в среде разработки IAR. Основное приложение успешно прошивается во flash память...

[РЕШЕНО] STM32F4 HardFault и CooCox
Добрый вечер! Как найти причину HordFault в STM32F4? Среда отладки CooCox

[Решено] HardFault при попытке настроить прерывание таймера
Здравствуйте. Недавно начал изучать ARM в общем и STM32 в частности, вылезла проблема при попытке сделать код для обработки событий от...

18
1 / 1 / 0
Регистрация: 05.10.2017
Сообщений: 2,048
08.08.2017, 14:18
Перед прыжком отключаете всё, включая SysTick? Раз расширили функционал, значит включили где-то тактирование на периферийном устройстве, и после прыжка, возможно пытаетесь проинитить его заново.
0
0 / 0 / 0
Регистрация: 30.12.2015
Сообщений: 74
08.08.2017, 14:32
Цитата Сообщение от Hotd
Перед прыжком отключаете всё, включая SysTick?
Угу, выключается.
Code
1
SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk;
Цитата Сообщение от Hotd
Раз расширили функционал, значит включили где-то тактирование на периферийном устройстве, и после прыжка, возможно пытаетесь проинитить его заново.
Периферия в загрузчике не используется вроде. Кроме SysTick. Но я всё равно копну ещё в ту сторону, вдруг найду :)
Если выпадает в ошибку в загрузчике, это не значит, что ошибка именно в загрузчике?
0
0 / 0 / 0
Регистрация: 26.01.2009
Сообщений: 3
08.08.2017, 14:38
А что нагенерировал компилятор для этого кусочка?
0
1 / 1 / 0
Регистрация: 05.10.2017
Сообщений: 2,048
08.08.2017, 14:42
FriiRTOS в загрузчике нет?
0
0 / 0 / 0
Регистрация: 30.12.2015
Сообщений: 74
08.08.2017, 14:44
Цитата Сообщение от div
А что нагенерировал компилятор для этого кусочка?
Не понял вопроса :(
Hotd, FriiRTOS нет.
Думаю совершить прыжок в другом месте, где ещё всякую периферию не инициализировал. Сейчас проверю.
0
0 / 0 / 0
Регистрация: 26.01.2009
Сообщений: 3
08.08.2017, 14:52
Цитата Сообщение от VysSpistotor
Код:
__disable_interrupt();
JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
Jump_To_Application = (pFunction) JumpAddress;
__set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
Jump_To_Application();

Ассемблерный код какой получился?
0
0 / 0 / 0
Регистрация: 30.12.2015
Сообщений: 74
08.08.2017, 14:55
Цитата Сообщение от div
Ассемблерный код какой получился?
Где его можно увидеть?
А ускоренный прыжок результатов не принёс, увы.
Если после манипуляций со стеком (__set_MSP) ругается на выход за пределы стека, это же нормально?
UPD: задумался, почему у меня JumpAddress сильно отличается от реального адреса, куда надо прыгнуть. Возможно, это мне и мешает.
0
1 / 1 / 0
Регистрация: 05.10.2017
Сообщений: 2,048
08.08.2017, 15:06
Прыжок для F1:
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
   typedef  void (*pFunction)(void);
pFunction   Jump_To_Application;
uint32_t   JumpAddress;
 
__disable_irq();      //запрещаем прерывания
 
//отключаем все прерывания в NVIC
NVIC->ICER[0] = 0xFFFFFFFF;
NVIC->ICER[1] = 0xFFFFFFFF;
NVIC->ICER[2] = 0xFFFFFFFF;
 
//очищаем все pending bit
NVIC->ICPR[0] = 0xFFFFFFFF;
NVIC->ICPR[1] = 0xFFFFFFFF;
NVIC->ICPR[2] = 0xFFFFFFFF;
 
//Peripheral risit enable (не трогаем reserved bits)
RCC->APB1RSTR = 0x3E7EC83F;
RCC->APB2RSTR = 0x00005E7D;
//Peripheral  risit disable
RCC->APB1RSTR = 0;
RCC->APB2RSTR = 0;
//Peripheral  disable clock
RCC->APB1ENR = 0;
RCC->APB2ENR = 0;
 
//вырубаем Systysk
SysTick->CTRL = 0;
SysTick->VOT = 0;
 
RCC_DeInit();
 
JumpAddress = *(uint32_t*)(MAIN_APP_ADDR + 4);
Jump_To_Application = (pFunction) JumpAddress;
 
NVIC_SetVectorTable( MAIN_APP_ADDR, 0 );      //перекидываем вектора
 
__set_MSP(*(vu32*) MAIN_APP_ADDR);
Jump_To_Application();
Прыжок для F4
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
   typedef  void (*pFunction)(void);
pFunction   Jump_To_Application;
uint32_t   JumpAddress;
 
__disable_irq();      //запрещаем прерывания
 
//отключаем все прерывания в NVIC
NVIC->ICER[0] = 0xFFFFFFFF;
NVIC->ICER[1] = 0xFFFFFFFF;
NVIC->ICER[2] = 0xFFFFFFFF;
 
//очищаем все pending bit
NVIC->ICPR[0] = 0xFFFFFFFF;
NVIC->ICPR[1] = 0xFFFFFFFF;
NVIC->ICPR[2] = 0xFFFFFFFF;
 
//Peripheral risit enable (не трогаем reserved bits)
RCC->AHB1RSTR = 0x22E017FF;
RCC->AHB2RSTR = 0x000000F1;
RCC->AHB3RSTR = 0x00000001;
RCC->APB1RSTR = 0xF6FEC9FF;
RCC->APB2RSTR = 0x04777933;
//Peripheral  risit disable
RCC->AHB1RSTR = 0;
RCC->AHB2RSTR = 0;
RCC->AHB3RSTR = 0;
RCC->APB1RSTR = 0;
RCC->APB2RSTR = 0;
//Peripheral  disable clock
RCC->AHB1ENR = 0x00100000;
RCC->AHB2ENR = 0;
RCC->AHB3ENR = 0;
RCC->APB1ENR = 0;
RCC->APB2ENR = 0;
 
//вырубаем Systysk
SysTick->CTRL = 0;
SysTick->VOT = 0;
 
RCC_DeInit();
 
JumpAddress = *(uint32_t*)(MAIN_APP_ADDR + 4);
Jump_To_Application = (pFunction) JumpAddress;
 
NVIC_SetVectorTable( MAIN_APP_ADDR, 0 );      //перекидываем вектора
 
__set_MSP(*(vu32*) MAIN_APP_ADDR);
Jump_To_Application();
В основной проге:
Code
1
2
3
4
void main()
{
NVIC_SetVectorTable( MAIN_APP_ADDR, 0 );      //перекидываем вектора
__enable_irq();      //разрешаем прерывания, т.к. в boottooder-е мы их запретили
Думаю что в L151 все схоже. Отключаем всю периферию в состояние ресета (дефолтными значениями), сбрасываем NVIC, отключаем systysk, отключаем всё тактирование (кварц и прочее) и прыгаем.
0
0 / 0 / 0
Регистрация: 30.12.2015
Сообщений: 74
08.08.2017, 15:16
Перекидывать вектора обязательно и в загрузчике, и в основной программе?
JumpAddress - что это за значение должно быть? По map-файлу основной прошивки указывает на Riset_Homdler. Так и надо ведь?
0
1 / 1 / 0
Регистрация: 05.10.2017
Сообщений: 2,048
08.08.2017, 15:32
эмс, это адрес начала вашей основной проги, так-то, обычно адрес страницы. Вы основную прогу куда размещаете? Вот туда и должен указывать адрес прыжка.
0
0 / 0 / 0
Регистрация: 30.12.2015
Сообщений: 74
08.08.2017, 15:55
Цитата Сообщение от Hotd
эмс, это адрес начала вашей основной проги, так-то, обычно адрес страницы. Вы основную прогу куда размещаете? Вот туда и должен указывать адрес прыжка.
Вписал туда свой адрес основной программы. Теперь висит в другом HordFault, основной программы :) Но перемещение таблицы прыжку поспособствовало. Или создало видимость прыжка...
UPD: Гарантированно рабочий загрузчик не захотел совершать прыжок. Придётся искать причину в основной прошивке.
0
0 / 0 / 0
Регистрация: 30.12.2015
Сообщений: 74
08.08.2017, 18:16
О чём может свидетельствовать ситуация, когда прыжок выполняется в зависимости от прошивки в основной области программы? То есть если эта прошивка там была изначально, то прыжок выполняется. Если эту же прошивку закидываю во FLASH повторно, тоже выполняется. А вот если загружу другую прошивку, прыжок не выполняется. То есть экспериментировал с прошивкой 1 и 2. При залитой прошивке 1 не хочет прыгать к 2. Аналогично при залитой прошивке 2 не хочет прыгать к 1. Что я мог упустить в процессе записи прошивки? Складывал исключительно в область основной прошивки. Может быть надо что-то в другие участки памяти записать?
div, Сгенерировал файл *.s.
код
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
GoMyApplication:
PUSH     {LR}
SUB      SP,SP,#+28
BL       FLASH_Tosk
BL       PowerOff
MOVS     R1,#+1
MOVS     R0,#+1
BL       RCC_AHBPeriphClockCmd
MOVS     R1,#+0
MOVS     R0,#+1
BL       RCC_AHBPeriphRisetCmd
MOV      R0,#+4096
STR      R0,[SP, #+0]
MOVS     R0,#+1
STRB     R0,[SP, #+4]
MOVS     R0,#+0
STRB     R0,[SP, #+6]
MOVS     R0,#+3
STRB     R0,[SP, #+5]
MOVS     R0,#+0
STRB     R0,[SP, #+7]
ADD      R1,SP,#+0
LDR.W    R0,??DataTable5_2  ;; 0x40020000
BL       GPIO_Init
LDR.W    R0,??DataTable5_3  ;; 0x4002001a
MOV      R1,#+4096
STRH     R1,[R0, #+0]
LDR.W    R0,??DataTable5_4
MOVS     R1,#+0
STR      R1,[R0, #+0]
??GoMyApplication_0:
LDR.W    R0,??DataTable5_4
LDR      R0,[R0, #+0]
CMP      R0,#+100
BCS.N    ??GoMyApplication_1
BL       CheckTimers
B.N      ??GoMyApplication_0
На что там обратить внимание? Придётся изучать ассемблер? :) Это только маленький кусочек.
0
-Otom-
09.08.2017, 13:55
У меня работает вот такая конструкция:
(Писалось для STM32F103 с некоторым количеством задействованой переферии.
Перед собственно переходом - отключаем всё, что может вызвать прерывание. Без этого почти гарантировано оказываемся в похожем обработчике.
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
void jump_app( uint32_t address ) {
__asm ("LDR SP, [R0]\n"); // Load new stack pointer address
__asm ("LDR PC, [R0, #4]\n");  //Load new program counter address;
};
uint8_t StartApp(void) {
uint32_t JumpAddress, sp;
JumpAddress = *(__IO uint32_t*) (APP_SECTION_START + 4);   // Riset homdler.
sp = *(__IO uint32_t*) (APP_SECTION_START);         // Load SP
if (JumpAddress >= APP_SECTION_END) {
return -1;
};
if (sp >= 0x2000FFFF) {
return -1;
};
delay_ms(100);
NVIC_DysableIRQ(DMA1_Channel4_IRQn);
DMA1_Channel4->CCR = 0;
USORT1->CR3 &= ~USORT_CR3_DMAT;
RCC->AHBENR &= ~RCC_AHBENR_DMA1EN;
RCC->APB2ENR &= ~RCC_APB2ENR_USORT1EN;
EXTI->IMR &= ~EXTI_IMR_MR16;
EXTI->RTSR &= ~EXTI_RTSR_TR16;
EXTI->FTSR &= ~EXTI_FTSR_TR16;
NVIC_DysableIRQ(PVD_IRQn);
SysTick->CTRL = 0;                  // Dysable SysTick.
SCB->VTOR = FLASH_BASE | 0x00008000;            // Move Vectors
jump_app(APP_SECTION_START);
return 0;
};
0 / 0 / 0
Регистрация: 30.12.2015
Сообщений: 74
09.08.2017, 14:50
Цитата Сообщение от -Otom-
У меня работает вот такая конструкция:
Спасибо за код. Но я почему-то виню код, который у меня лежит в основной области FLASH :) Собственно, прыжок у меня выполняется, оказываюсь в Riset_Homdler основной программы, там даже System_init выполняется. А вот до main не доходит. Узнал это, сместив вектора в процедуре System_init. Теперь HordFault висит в новой области FLASH :) Хотел проконтролировать расход оперативной памяти, да пока что не представляю, как это сделать.
В ассемблерном коде что-то крутится в цикле (возможно, в бесконечном), потом выпадает в ошибку.
Крутится где-то в __iar_program_stort, который идёт сразу после System_init.
0
-Otom-
09.08.2017, 16:09
Советую добавить пустые обработчики неописаных прерываний вида:
Code
1
2
3
4
5
6
void WWDG_IRQHomdler(void) { while(1) {}; };
void TAMPER_IRQHomdler(void) { while(1) {}; };
void RTC_IRQHomdler(void) { while(1) {}; };
void FLASH_IRQHomdler(void) { while(1) {}; };
void RCC_IRQHomdler(void) { while(1) {}; };
...
Очень помогает понять, какое прерывание было выполнено из неописаных. Естественно, дублирующиеся нужно будет убирать.

Если используете отладчик (лично я - arm-none-eabi-gdb + st-util) - то можно посмотреть стэк вызовов и хотя бы примерно определить причину произошедшего. Там же по адресам можно установить более детальную картину.
0 / 0 / 0
Регистрация: 30.12.2015
Сообщений: 74
09.08.2017, 16:19
Цитата Сообщение от -Otom-
Очень помогает понять, какое прерывание было выполнено из неописаных.
То есть предполагается, что у меня возникает прерывание, которое и сваливает МК в HordFault?
Цитата Сообщение от -Otom-
...можно посмотреть стэк вызовов и хотя бы примерно определить причину произошедшего. Там же по адресам можно установить более детальную картину.
Вижу стек. Есть столбец Location (адрес в оперативной памяти?) и Data (адрес функции, смотрю в map-файле). Если я всё понимаю верно, сейчас прослежу, откуда я попадаю в HordFault.
Чем больше адрес в Location, тем позже (глубже) вызывается функция?
0
0 / 0 / 0
Регистрация: 30.12.2015
Сообщений: 74
09.08.2017, 17:32
CSTACK в IAR показывает кучу адресов, включая полностью состоящие из нулей. Далеко не все есть в map-файле. Последняя запись в момент повисания - это функция _call_main. В режиме отладки в ассемблерном коде у неё две инструкции: MOVS и BL main.
Похоже, даже чтобы немного понять причину, придётся изучать ассемблер.
UPD: а скорее _call_main даже вызывалась первой, а не последней. Дальше идут непонятные адреса.
0
0 / 0 / 0
Регистрация: 30.12.2015
Сообщений: 74
10.08.2017, 11:57
Всем спасибо за поддержку. Проблема решена.
Получил новые знания. А причина банальна. Когда складывал новую прошивку, копировал данные не полностью. Поэтому запускаемая прошивка была нерабочей.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
10.08.2017, 11:57
Помогаю со студенческими работами здесь

FATFS и HardFault
Доброго времени суток! Играюсь с LPC1769 (ARM M3). точнее прикручиваю Fat_FS. В процессе возникла проблемма с вылетом в Hord_Fault. ...

Отладка HardFault
С праздником, коллеги! Иногда у меня выскакивает HordFault. Где и почему? Ответ на этот вопрос усложняется тем, что этот HordFault...

Ошибки HardFault
Добрый день, столкнулся с проблемой, код писали до меня и из-за какой то причины возникает ошибка HardFault. Работаю с cortex m0. ...

STLink HardFault LR = 0xfffffff9
Народ, нужна помощь. Уже месяц периодически возвращаюсь к этому. Устройство на stm32f030f4p6. Благо все заработало у меня без отладки - то...

HardFault при запуске
Привет всем! Имеется STM320F072B-DISCO, пытаюсь в мигание светодиодом, IDE - STM32Cube. При пуске ничего не происходит, если включить...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
19
Ответ Создать тему
Опции темы

Новые блоги и статьи
Использование SDL3-callbacks вместо функции main() на Android, Desktop и WebAssembly
8Observer8 24.01.2026
Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а привычная функция main(). . .
моя боль
iceja 24.01.2026
Выложила интерполяцию кубическими сплайнами www. iceja. net REST сервисы временно не работают, только через Web. Написала за 56 рабочих часов этот сайт с нуля. При помощи perplexity. ai PRO , при. . .
Модель сукцессии микоризы
anaschu 24.01.2026
Решили писать научную статью с неким РОманом
http://iceja.net/ математические сервисы
iceja 20.01.2026
Обновила свой сайт http:/ / iceja. net/ , приделала Fast Fourier Transform экстраполяцию сигналов. Однако предсказывает далеко не каждый сигнал (см ограничения http:/ / iceja. net/ fourier/ docs ). Также. . .
http://iceja.net/ сервер решения полиномов
iceja 18.01.2026
Выкатила http:/ / iceja. net/ сервер решения полиномов (находит действительные корни полиномов методом Штурма). На сайте документация по API, но скажу прямо VPS слабенький и 200 000 полиномов. . .
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ * Дана цепь(не выше 3-го порядка) постоянного тока с элементами R, L, C, k(ключ), U, E, J. Программа находит переходные токи и напряжения на элементах схемы классическим методом(1 и 2 з-ны. . .
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым. Но восстановить их можно так. Для этого понадобится консольная утилита. . .
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru