|
|
  |
Hard Fault Exception на кортексе м3, как узнать откуда прилезло |
|
|
|
Feb 28 2014, 04:36
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(jcxz @ Feb 28 2014, 08:32)  Вот только не надо передёргивать! Тут есть история и всегда можно посмотреть о чём и когда шла речь. Во-первых - вызов перегруженного члена класса не может осуществляться BL, а только командами BLX; BX; LDR PC, ...; (возможно ещё TBB/TBH) - почитайте последние сообщения тут, чтобы понять почему. Ох, ну что же вы такой упёртый-то. Ну давайте почитаем. Вот исходное сообщение, с которого всё началось (выделение жирным - моё): Цитата(juvf @ Feb 26 2014, 00:54)  Выпадаю в Hard Fault Exception. описал обработчик, получил вывод [skip] LR = 0x8002c09 PC = 0x20001498 Вот мой ответ: Цитата(AHTOXA @ Feb 26 2014, 17:30)  Посмотрите команду, которая находится перед 0x8002c08, возможно дело в ней. juvf посмотрел: Цитата(juvf @ Feb 26 2014, 18:28)  перед 0x8002c09 такой код Код LDR R1, [R1] LDR R1,[R1, #0x8] BLX R1 CMP R0,#0 [skip] падает в перегруженном операторе -- if(--(*(MyClass*)p) ) { } Видите, всё именно так, как я описал. В регистре LR - адрес, следующий после адреса проблемного вызова. То есть, по сути, мы уже нашли место возникновения проблемы: Цитата(AHTOXA @ Feb 26 2014, 18:54)  Команда BLX R1 должна прыгать на код вашего перегруженного оператора, а вместо этого прыгает в ОЗУ. Да, похоже, что память портится. И тут, как чёрт из табакерки, выскочили вы, и начали умничать. Я бы уже давно перестал отвечать на ваши петушиные наскоки, но всё надеялся, что вы перечитаете тему, переосмыслите и признаете свою неправоту. Однако теперь вижу, что это бесполезно. Думаю, что в этом ответе я предельно чётко подытожил описание проблемы и её решение. Надеюсь, это поможет кому-то, кто будет читать эту тему потом. Что касаемо дальнейшей дискуссии с вами, то я не вижу в ней никакого смысла.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Mar 30 2017, 15:27
|

Профессионал
    
Группа: Свой
Сообщений: 1 261
Регистрация: 14-05-09
Из: Челябинск
Пользователь №: 49 045

|
stm32 L052 падает в HF пытаюсь сделать обработчик HF и вывести содержимое регистров. вставляю в обработчик Код asm volatile ( "TST LR, #4 \n " "ITE EQ \n" "MRSEQ R0, MSP \n" "MRSNE R0, PSP \n" "B hardfault_handler " ); - не компилиться. пишет Updating build tree... Код stm32l0xx_it.c Error[Og006]: Error in inline assembly: "Error[401]: Operand syntax error" ...\Src\stm32l0xx_it.c 107 Error[Og006]: Error in inline assembly: "Error[438]: This instruction is not available in the selected cpu/core" ...\Src\stm32l0xx_it.c 108 Error while running C/C++ Compiler на строчку "TST LR, #4" и "ITE EQ". Погуглив гдето на форумах было задето, что возможно это из-за того, что препроцессор в режиме Thumb. Но как его на ARM переключить? Собираю в ИАРе сгенерированный проект из куба. в настройках выбран Thumb и выбор режима ARM или Thumb заблокирован. Как можно отловить HF?
Эскизы прикрепленных изображений
|
|
|
|
|
Mar 30 2017, 16:10
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(juvf @ Mar 30 2017, 20:27)  Error[Og006]: Error in inline assembly: "Error[401]: Operand syntax error" ...\Src\stm32l0xx_it.c 107 Error[Og006]: Error in inline assembly: "Error[438]: This instruction is not available in the selected cpu/core" ...\Src\stm32l0xx_it.c 108 Это Cortex-M0(+)/Cortex-M1. У них нет инструкции ITE. Для них надо вот так: Код void HardFault_Handler(void) { asm volatile ( " MOV R0, LR \n" " CMP R0, #4 \n" " BNE hf_psp%= \n"
"hf_msp%=: \n" " MRS R0, MSP \n" " B hard_fault_handler \n"
"hf_psp%=: \n" " MRS R0, PSP \n" " B hard_fault_handler \n" : // no output : [param]"r" (0) // dummy param : // no clobbers ); } (Это для gcc, для IAR-а сами подправьте).
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Mar 31 2017, 03:34
|

Профессионал
    
Группа: Свой
Сообщений: 1 261
Регистрация: 14-05-09
Из: Челябинск
Пользователь №: 49 045

|
Цитата(jcxz @ Mar 30 2017, 22:03)  Препроцессор только в одном режиме может работать - в режиме си. опечатался, процессор Цитата(AHTOXA @ Mar 30 2017, 21:10)  Это Cortex-M0(+)/Cortex-M1. У них нет инструкции ITE. Спасибо АНТОХА!!! В очередной раз выручил. для иара (кубовски проект) в файле stm32l0xx_it.c нужно в юзеркод вставить так Код /* USER CODE BEGIN 0 */ void hard_fault_handler (unsigned int * hardfault_args) { unsigned int stacked_r0; unsigned int stacked_r1; unsigned int stacked_r2; unsigned int stacked_r3; unsigned int stacked_r12; unsigned int stacked_lr; unsigned int stacked_pc; unsigned int stacked_psr;
stacked_r0 = ((unsigned long) hardfault_args[0]); stacked_r1 = ((unsigned long) hardfault_args[1]); stacked_r2 = ((unsigned long) hardfault_args[2]); stacked_r3 = ((unsigned long) hardfault_args[3]);
stacked_r12 = ((unsigned long) hardfault_args[4]); stacked_lr = ((unsigned long) hardfault_args[5]); stacked_pc = ((unsigned long) hardfault_args[6]); stacked_psr = ((unsigned long) hardfault_args[7]);
printf ("[Hard fault handler]\n"); printf ("R0 = 0x%x\n", stacked_r0); printf ("R1 = 0x%x\n", stacked_r1); printf ("R2 = 0x%x\n", stacked_r2); printf ("R3 = 0x%x\n", stacked_r3); printf ("R12 = 0x%x\n", stacked_r12); printf ("LR = 0x%x\n", stacked_lr); printf ("PC = 0x%x\n", stacked_pc); printf ("PSR = 0x%x\n\n", stacked_psr); printf ("Execute code from 0x%x\n\n", stacked_pc); printf ("See command befor 0x%x\n\n", stacked_lr); for(;;); } /* USER CODE END 0 */
...
void HardFault_Handler(void) { /* USER CODE BEGIN HardFault_IRQn 0 */ asm volatile ( " MOV R0, LR \n" " CMP R0, #4 \n" " BNE hf_psp \n"
"hf_msp: \n" " MRS R0, MSP \n" " B hard_fault_handler \n"
"hf_psp: \n" " MRS R0, PSP \n" " B hard_fault_handler \n" : // no output : [param]"r" (0) // dummy param : // no clobbers );
/* USER CODE END HardFault_IRQn 0 */ while (1) { } /* USER CODE BEGIN HardFault_IRQn 1 */
/* USER CODE END HardFault_IRQn 1 */ }
|
|
|
|
|
Mar 31 2017, 09:02
|
Знающий
   
Группа: Участник
Сообщений: 758
Регистрация: 27-08-08
Пользователь №: 39 839

|
Цитата(juvf @ Mar 31 2017, 11:30)  По мойму нельзя. Можно. Более того есть смысл оформить обработчик так: Код void Default_Handler(void) { volatile int i = 1; while (i) { } } Тогда можно переменную i в отладчике поменять на 0 и пройтись до выхода из HardFault, выйдет как раз в место его возникновения, бывает очень удобно. Можно конечно адрес из стека вытащить, но так проще, удобней, нагляднее.
|
|
|
|
|
Mar 31 2017, 09:08
|

Профессионал
    
Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831

|
Цитата(ViKo @ Mar 31 2017, 11:14)  Можно. Только, когда ошибка появляется в рабочем приборе, вдалеке от отладчика, вот тогда нужно пересылать информацию. Все HF следует отлавливать еще на этапе отладки и прогона на месте, иначе грош-цена такому коду. А вот для фиксации различных событий и т. п. следует использовать самописный или готовый журнал событий, который писать на внешнюю или внутр. флэшку. В этом случае можно спокойно проанализировать записи в журнале за некий период работы, просто переслав разработчику соотв. файл журнала событий. Для этого никуда ездить не нужно. Если есть доступ в сеть, то можно научить девайс писать журнал сразу наружу, да хоть на "облако" ))
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Mar 31 2017, 09:13
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(Шаманъ @ Mar 31 2017, 11:02)  Тогда можно переменную i в отладчике поменять на 0 и пройтись до выхода из HardFault, выйдет как раз в место его возникновения, бывает очень удобно. Можно конечно адрес из стека вытащить, но так проще, удобней, нагляднее. У Cortex есть неточные ошибки с памятью (Imprecise Bus Fault). Так Вы их место не найдёте. А через регистры - найдёте. Да и очень неудобно каждый раз вспоминать где какой стек, лучше иметь готовый код. Не зря же даже в винде подобный обработчик сделали с регистрами и стеком (синий экран). Вот у меня как раз подобный для Cortex есть  Цитата(Forger @ Mar 31 2017, 11:08)  Все HF следует отлавливать еще на этапе отладки и прогона на месте, иначе грош-цена такому коду. А вот для фиксации различных событий и т. п. следует использовать самописный или готовый журнал событий, который писать на внешнюю или внутр. флэшку. Это конечно всё хорошо и правильно. Но на практике почему-то случаются такие ошибки (в том числе и HF), которые проявляются почему-то только у заказчика Вот тут-то фиксация в журнал спасает (а особенно - в энергонезависимый).
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|