koluna 0 12 августа Опубликовано 12 августа · Жалоба Здравствуйте! Прошу помочь разобраться. Процессор STM32F100R8, компилятор GCC. Периодически возникает исключение Hard Fault. В обработчике считал следующие регистры: HFSR=x40000000 CFSR=x00008200 Читаю описание и понять ничего не могу... В чем может быть проблема? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 12 августа Опубликовано 12 августа · Жалоба Там на стеке должны еще некоторые регистры лежать. Очень помогает сохраненные значения LR и PC. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 183 12 августа Опубликовано 12 августа · Жалоба Под отладчиком для начала стоило бы хотя бы посмотреть стек вызовов. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
EdgeAligned 85 12 августа Опубликовано 12 августа · Жалоба Накосячил в коде. Если ошибка возникает периодически, то, как правило, что-то в роде обращения по неинициализованному указателю (произвольное значение указателя), либо выход за пределы адресов реализованной памяти. Если развернута RTOS, может портиться содержимое стека задачи или стека вызовов. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
koluna 0 12 августа Опубликовано 12 августа · Жалоба On 8/12/2024 at 8:59 PM, adnega said: Там на стеке должны еще некоторые регистры лежать. Очень помогает сохраненные значения LR и PC. Считать в обработчике по адресу из MSP? On 8/12/2024 at 9:03 PM, Arlleex said: Под отладчиком для начала стоило бы хотя бы посмотреть стек вызовов. Конкретизируйте, пожалуйста. Что я могу увидеть в стеке вызовов? On 8/12/2024 at 9:18 PM, EdgeAligned said: Накосячил в коде. Если ошибка возникает периодически, Периодически возникает, через несколько минут после старта. Обычный дебаг не помогает уже... On 8/12/2024 at 9:18 PM, EdgeAligned said: как правило, что-то в роде обращения по неинициализованному указателю (произвольное значение указателя), либо выход за пределы адресов реализованной памяти. Уже глаза сломал в код смотреть... упростил и отключил все по максимуму... On 8/12/2024 at 9:18 PM, EdgeAligned said: Если развернута RTOS, может портиться содержимое стека задачи или стека вызовов. РТОСа нет. Прототреды использую. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Priest_89 8 12 августа Опубликовано 12 августа · Жалоба Если работаете в TrueStudio или CubeIDE, в них есть утилита Fault Analyzer, которая выводит всю информацию о HardFault, в том числе адрес инструкции, которая его вызвала. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
koluna 0 12 августа Опубликовано 12 августа · Жалоба On 8/12/2024 at 9:58 PM, Priest_89 said: Если работаете в TrueStudio или CubeIDE, в них есть утилита Fault Analyzer, которая выводит всю информацию о HardFault, в том числе адрес инструкции, которая его вызвала. Нет. У меня в чистом виде GCC и другая IDE. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 183 12 августа Опубликовано 12 августа · Жалоба 56 минут назад, koluna сказал: Конкретизируйте, пожалуйста. Что я могу увидеть в стеке вызовов? Я к тому, что начинать надо с простейшего, а анализ стека вызовов во многих случаях позволяет успешно локализовать баг, даже без анализа регистров HF. Например, начать с проверки, одинаков ли стек вызовов при паре-тройке проявлений бага. 3 часа назад, koluna сказал: Здравствуйте! Прошу помочь разобраться. Процессор STM32F100R8, компилятор GCC. Периодически возникает исключение Hard Fault. В обработчике считал следующие регистры: HFSR=x40000000 CFSR=x00008200 Читаю описание и понять ничего не могу... В чем может быть проблема? Считайте BFAR и в нем будет адрес инструкции, которая вызвала ошибку. Из активного стека нужно вычленить аргументы (регистры), по ним уже и смотреть, откуда туда могло попасть то, что попало и вызвало эскалацию до HF. BusFault - как правило, либо пытаетесь "лезть" по адресу, по которому лезть нельзя (например, адрес несуществующей или неактивной периферии). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 12 августа Опубликовано 12 августа · Жалоба 1 час назад, koluna сказал: Считать в обработчике по адресу из MSP? Типа такого: Обработчик: HardFaultException: mov r0, sp push {lr} bl print_fault pop {pc} Си-функция: void print_fault(sFAULT *fault) { static int cnt = 0; if(cnt < 5) { con_str("FAULT:\n\r"); con_str("r0 = "); con_dword(fault->r0); con_str(", "); con_str("r1 = "); con_dword(fault->r1); con_str(", "); con_str("r2 = "); con_dword(fault->r2); con_str(", "); con_str("r3 = "); con_dword(fault->r3); con_str("\n\r"); con_str("r12 = "); con_dword(fault->r12); con_str(", "); con_str("lr = "); con_dword(fault->lr); con_str(", "); con_str("pc = "); con_dword(fault->pc); con_str(", "); con_str("xpsr = "); con_dword(fault->xpsr); con_str("\n\r"); con_start(); cnt++; } } typedef struct sFAULT { uint32_t r0; uint32_t r1; uint32_t r2; uint32_t r3; uint32_t r12; uint32_t lr; uint32_t pc; uint32_t xpsr; } sFAULT; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
koluna 0 12 августа Опубликовано 12 августа · Жалоба Подцепил отладчик... пытаюсь понять что там и как... (gdb) backtrace #0 HardFault_Handler () at ./src/main.c:116 #1 <signal handler called> #2 0x08001682 in exchTXEHandler () at ./src/libs/exchange/exchange.c:341 #3 <signal handler called> #4 dbgout (level=level@entry=7, format=0x80017c7 <EXCH_process+266> "H\377\367\004\370\262#+\200\252\347\201N") at ./src/libs/dbg/dbg.c:19 #5 0x080017c6 in waitForRequest (exchRes=0x20000f20 <exchRes.7247>, pt=0x20000f2c <ptChild.7246>) at ./src/libs/exchange/exchange.c:175 #6 EXCH_process (pt=0x20001fec) at ./src/libs/exchange/exchange.c:461 #7 0xf4f377fc in ?? () Backtrace stopped: previous frame identical to this frame (corrupt stack?) Это стек вызовов... Настораживает последняя строчка. Не понимаю, что такое <signal handler called> On 8/12/2024 at 10:36 PM, Arlleex said: Считайте BFAR и в нем будет адрес инструкции, которая вызвала ошибку. Да, счтал давно: [HardFault_Handler()] BFAR=x20002000 Да, это Bus Fault, я уже понял. И адрес RAM. В просессоре 8 кБ, как раз на конец указывает, только вот что это значит... On 8/12/2024 at 10:36 PM, Arlleex said: BusFault - как правило, либо пытаетесь "лезть" по адресу, по которому лезть нельзя (например, адрес несуществующей или неактивной периферии). Да там элементарный код в нескольких функциях, я ума не приложу что там не так пошло... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 183 12 августа Опубликовано 12 августа · Жалоба Дык может стоит выложить код, если не секретный? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 12 августа Опубликовано 12 августа · Жалоба Кста, у меня бага была на GD-проце. По идее, ядро после перезагрузки должно стек проинициализировать (первое слово) и управление передать (второе слово). У меня почему-то стек не инициализировался ядром - пришлось ручками задавать. Тоже вспотел - минимальнейший проект не работал) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
EdgeAligned 85 13 августа Опубликовано 13 августа · Жалоба 8 часов назад, koluna сказал: Да там элементарный код в нескольких функциях, я ума не приложу что там не так пошло... Если ошибка непостоянная, а проявляется временами, то она не будет видна явно в коде. 10 часов назад, koluna сказал: Прототреды использую Что-то тут с потоками накосячил. Убери эти недопотоки и проверь код без них. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
koluna 0 13 августа Опубликовано 13 августа · Жалоба On 8/13/2024 at 12:28 AM, Arlleex said: Дык может стоит выложить код, если не секретный? Не секретный. Можно выложить. Проблема в том, что проверить полноценно не удастся: там два устройства, второе устройство обменивается по USART с глючащим устройством... On 8/13/2024 at 2:32 AM, adnega said: Кста, у меня бага была на GD-проце. По идее, ядро после перезагрузки должно стек проинициализировать (первое слово) и управление передать (второе слово). У меня почему-то стек не инициализировался ядром - пришлось ручками задавать. Тоже вспотел - минимальнейший проект не работал) У меня скрипт линкера и стартап из scmRTOS. В ОЗУ, вроде, нормально все влезает. Посмотрел по map-файлу. Указатель на стек формируется в скрипте линкера, в стартапе вместе с таблицей подгружается. typedef void(*const intfunc)(void); __attribute__ ((section(".isr_vector"))) intfunc g_pfnVectors[] = { /* Core interrupt vectors */ (intfunc)((unsigned long)&_estack), Reset_Handler, NMI_Handler, Прошелся по функциям - нигде нет огромных переменных и, соответственно, переполнения стека. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
EdgeAligned 85 13 августа Опубликовано 13 августа · Жалоба --- Ты чего тут по полу ползаешь? --- Да я вон там ключи потерял, ищу... --- Так и ищи там, где потерял --- Так здесь светлее же! Напишите обработчик прерывания void HardFault_Handler(void){ while(1) ; } и поставьте на нем брейкпоинт, запустите отладку. При остановке посмотрите отладочную инфу с указанием адреса инструкции, вызвавшей "тяжелый сбой". Откройте листинг кода и по адресу найдите, какая инструкция и к чему (какому куску кода) она принадлежит. Далее будет видно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться