|
Hard Fault Exception на кортексе м3, как узнать откуда прилезло |
|
|
|
 |
Ответов
|
Feb 25 2014, 18:54
|

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

|
Выпадаю в Hard Fault Exception. описал обработчик, получил вывод [Hard fault handler] R0 = 0x200014a0 R1 = 0x20001498 R2 = 0x2000123c R3 = 0x20001980 R12 = 0x10003 LR = 0x8002c09 PC = 0x20001498 PSR = 0x8000000f 1)как понять от куда ноги растут у проблемы? Подозреваю что не хватает кучи. при увеличении кучи в HF не попадаю. но может есть утечка, и увеличив кучу я просто оттянул конец. LR = 0x8002c09 - по этому адресу в дизассемблере нет команды. есть команда по адресу Код 0x8002c08: 0x2800 CMP R0,#0 PC = 0x20001498 это похоже куча, из мэпа Код "P2", part 3 of 3: 0x6d8 HEAP 0x20001480 0x300 <Block> HEAP uninit 0x20001480 0x300 <Block tail> CSTACK 0x20001780 0x200 <Block> CSTACK uninit 0x20001780 0x200 <Block tail> .noinit uninit 0x20001980 0x1d8 config.o [1] - 0x20001b58 0x6d8 2)В какой документации описан регистр LR? 3)в документации на М3 "STM32F10xxx Cortex-M3 programming manual" есть описание регистра Цитата Hard fault status register (SCB_HFSR) Address offset: 0x2C Reset value: 0x0000 0000 Required privilege: Privileged The HFSR gives information about events that activate the hard fault handler. Почему среди регистров в дебаггире в EW IAR нет регистра HFSR? ps EW IAR, STM32F100C8T6
|
|
|
|
|
Feb 27 2014, 02:20
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(AHTOXA @ Feb 26 2014, 17:30)  Судя по , при возникновении исключения выполнялся код в ОЗУ (0x20001498). Посмотрите команду, которая находится перед 0x8002c08, возможно дело в ней. Почему Вы решили, что в LR - адрес возврата из функции, в которой произошло исключение? Имхо - там может быть что угодно. Пример: PUSH {...,LR} ;стандартный вход в функцию, вызывающую другие функции ... BL some_func С этого места в LR - может быть, что угодно, может адрес этой инструкции, а может и что-то другое если возврат из some_func осуществлялся чем-то вроде POP {..., PC}, а не BX LR. А ещё - оптимизатор может использовать LR как обычный РОН. После улёта исполнения кода в произвольное место в ОЗУ, определить можно только адрес (PC), где произошло исключение. Об остальном - только гадать. Когда я боролся с подобной проблемой, я сделал монитор регистров CPU, повесил его на высокочастотное IRQ от таймера (такое чтобы давало >90% загрузки CPU). В ISR просто писал дамп регистров CPU (и ближайшего стека) в FIFO таких дампов в ОЗУ. При наступлении сбоя - смотрел последовательность этих дампов и определял где было последнее валидное состояние. Расстояние между такими дампами получалось всего несколько десятков команд - место сбоя ловилось довольно точно. Ну или нужен какой-то аппаратный трэйсер с запоминанием потока команд и возможностью отмотать назад.
|
|
|
|
|
Feb 27 2014, 05:21
|

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

|
Цитата(jcxz @ Feb 27 2014, 08:20)  Почему Вы решили, что в LR - адрес возврата из функции, в которой произошло исключение? Имхо - там может быть что угодно. Потому что обычно там находится адрес возврата  И обычно компилятор использует LR именно для этих целей. Цитата(jcxz @ Feb 27 2014, 08:20)  Пример: PUSH {...,LR} ;стандартный вход в функцию, вызывающую другие функции ... BL some_func С этого места в LR - может быть, что угодно С этого места в LR как раз адрес возврата. Так работает инструкция BL. Цитата(jcxz @ Feb 27 2014, 08:20)  А ещё - оптимизатор может использовать LR как обычный РОН. Не встречал такого. Компилятор знает, что там находится адрес возврата (он сам его туда положил). Поэтому обычно старается его не трогать. Если вы встречали такое, то приведите пример. Цитата(jcxz @ Feb 27 2014, 08:20)  После улёта исполнения кода в произвольное место в ОЗУ, определить можно только адрес (PC), где произошло исключение. А вот это обычно как раз бесполезная инфа. Ибо в случае, когда исключение вызвано улётом в несуществующие адреса, значение этого несуществующего адреса не представляет никакого интереса. А вот откуда мы прыгнули на этот несуществующий адрес - это информация очень нужная. И эта информация как раз с хорошей вероятностью лежит в регистре LR.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Feb 27 2014, 06:09
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(AHTOXA @ Feb 27 2014, 11:21)  Потому что обычно там находится адрес возврата И обычно компилятор использует LR именно для этих целей. Адрес возврата в LR внутри функции хранится только если в функции нет вложенных вызовов других функций. Подумайте почему. Цитата(AHTOXA @ Feb 27 2014, 11:21)  С этого места в LR как раз адрес возврата. Так работает инструкция BL. Как работает инструкция BL я прекрасно знаю. Но не она возвращает управление из функции some_func. Управление возвращается обычно или BX LR или чем-то вроде POP {...,PC}(если в той функции было сохранение LR на стеке (были вложенные вызовы других функций)). Во втором случае в LR будет не то что вы ожидаете. Цитата(AHTOXA @ Feb 27 2014, 11:21)  Не встречал такого. Компилятор знает, что там находится адрес возврата (он сам его туда положил). Поэтому обычно старается его не трогать. Если вы встречали такое, то приведите пример. То что вы этого не встречали, говорит о том, что вы никогда не заглядывали в листинги компилятора. После того как LR был сохранён на стеке, содержимое LR больше не нужно и при необходимости может использоваться для временных переменных компилятором. Если угодно, вот пример из моего проекта (IAR6.50): CODE static void KeyboardScan() { _Z12KeyboardScanv: 0xE92D 0x41F0 PUSH {R4-R8,LR} static u8 m[ncell(kbdKeyPins)] = {0, 0 Depend3Keys(, 0)}; static u16 tLight; int c = 0, c1, n = ncell(kbdKeyPins) - 1; 0x.... 0x.... LDR.W R2,??DataTable28_5 0x.... 0x.... ADR.W R4,kbdKeyPins+0x4 0x.... 0x.... LDR.W R6,??DataTable28_1 0x.... 0x.... LDR.W R7,??DataTable28_4 0x2000 MOVS R0,#+0 0x2102 MOVS R1,#+2 0xF202 0x0306 ADDW R3,R2,#+6 0xF44F 0x5500 MOV R5,#+8192 do { if (Pdat2(kbdKeyPins[n].port, kbdKeyPins[n].pin)) { ??KeyboardScan_0: 0xF894 0xE000 LDRB LR,[R4, #+0] 0xF893 0xC000 LDRB R12,[R3, #+0] 0xEB07 0x1E4E ADD LR,R7,LR, LSL #+5 0xF8DE 0xE014 LDR LR,[LR, #+20] 0xF894 0x8001 LDRB R8,[R4, #+1] 0xFA2E 0xFE08 LSR LR,LR,R8 0xEA5F 0x7ECE LSLS LR,LR,#+31 0xD50D BPL.N ??KeyboardScan_1 Цитата(ViKo @ Feb 27 2014, 11:51)  При прерываниях адрес возврата сохраняется в стек (там его можно и найти, положение известно). А в LR заносится специальное слово EXC_RETURN (там почти одни единицы). Разговор не о LR в CPU, а о LR из фрейма, сохранённом на стеке при стекинге перед входом в ISR.
|
|
|
|
|
Feb 27 2014, 08:46
|

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

|
Цитата(jcxz @ Feb 27 2014, 12:09)  Адрес возврата в LR внутри функции хранится только если в функции нет вложенных вызовов других функций. Подумайте почему. Я бы сформулировал это по другому: "Бывают случаи, когда LR не содержит адрес возврата. Но чаще всего - содержат". Цитата(jcxz @ Feb 27 2014, 12:09)  Как работает инструкция BL я прекрасно знаю. Ой ли. Я отвечал на вот эту конкретную вашу фразу: Цитата(jcxz @ Feb 27 2014, 08:20)  BL some_func С этого места в LR - может быть, что угодно Судя по ней, вы не знаете как работает BL. Цитата(jcxz @ Feb 27 2014, 12:09)  Если угодно, вот пример из моего проекта (IAR6.50): Ну вот и посмотрите на свой пример. Более половины времени выполнения функции в LR находится адрес возврата  И ещё одно соображение. Если HardFault вызван переходом по несуществующему адресу (а это как раз случай, о котором спрашивал juvf), то LR содержит адрес возврата гарантированно, поскольку по несуществующему адресу нет кода, который может "сохранить на стек LR и использовать его для каких-то других целей".
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Feb 27 2014, 09:11
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(AHTOXA @ Feb 27 2014, 14:46)  Судя по ней, вы не знаете как работает BL. Из чего вы сделали такой вывод? Что же там по вашему в LR??? Цитата(AHTOXA @ Feb 27 2014, 14:46)  Ну вот и посмотрите на свой пример. Более половины времени выполнения функции в LR находится адрес возврата  Каким образом интересно вы вычислили время выполнения и размер функции??? И причём это тут вообще? Цитата(AHTOXA @ Feb 27 2014, 14:46)  И ещё одно соображение. Если HardFault вызван переходом по несуществующему адресу (а это как раз случай, о котором спрашивал juvf), то LR содержит адрес возврата гарантированно, поскольку по несуществующему адресу нет кода, который может "сохранить на стек LR и использовать его для каких-то других целей". И что? С чего вы решили что до перехода там содержался адрес возврата??? PS: Блин - вместо того чтобы тут нести чушь, почитайте лучше описание системы команд! Большего количества чуши в одном сообщении трудно найти....
|
|
|
|
|
Feb 27 2014, 10:54
|

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

|
Цитата(jcxz @ Feb 27 2014, 15:11)  И что? С чего вы решили что до перехода там содержался адрес возврата??? Потому что так в кортексах происходит вызов функций - командой BL. Эта команда заносит в LR адрес следующей инструкции (адрес возврата). И затем заносит в PC новый адрес. Если этот новый адрес не существует, то происходит HardFault. И если в обработчике HardFault-а достать из стека сохранённый в момент возникновения исключения LR, то он будет содержать адрес возврата. Вашу следующую реплику я возвращаю вам: Цитата(jcxz @ Feb 27 2014, 15:11)  PS: Блин - вместо того чтобы тут нести чушь, почитайте лучше описание системы команд! Большего количества чуши в одном сообщении трудно найти....
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Feb 27 2014, 11:51
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(AHTOXA @ Feb 27 2014, 16:54)  Потому что так в кортексах происходит вызов функций - командой BL. Причём тут "вызов функций"?? Вы пишете переходом по несуществующему адресу. Неужто такие переходы могут быть только по команде BL? Может тогда просто - удалить её нафик из системы команд и не будет проблем?  А как же всякие BX Rx, POP {PC}, LDR PC, ... и пр.? Вы такие команды знаете? И что происходит при нехватке стека? Уж-ли не из-за POP {PC} за пределами стека может вызвать переход по несуществующему адресу? И как интересно команда BL addr может вызвать переход по несуществующему адресу, если адрес перехода находится в теле самой команды, которая скорее всего находится во FLASH и этот адрес формирует линкёр???
|
|
|
|
|
Feb 27 2014, 15:00
|

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

|
Цитата(juvf @ Feb 27 2014, 17:48)  Думаю, что я нашел граблю. Аминь!  Цитата(jcxz @ Feb 27 2014, 17:51)  Причём тут "вызов функций"?? При том, что мы с вами вели речь про оператор BL. Помните, я вам объяснял, как он работает? Так вот. Оператор BL - это вызов функции. Поэтому я и пишу про вызов функции. Напомню также, что у juvf речь шла о вызове перегруженного оператора. А это - тоже вызов функции. Цитата(jcxz @ Feb 27 2014, 17:51)  Вы пишете переходом по несуществующему адресу. Неужто такие переходы могут быть только по команде BL? Переходы, вызванные вызовом функции - да. Цитата(jcxz @ Feb 27 2014, 17:51)  Может тогда просто - удалить её нафик из системы команд и не будет проблем?  А как же всякие BX Rx, POP {PC}, LDR PC, ... и пр.? Вы такие команды знаете? Я знаю много разных команд. А ещё я знаю стихи Маяковского. Но ни то ни другое не связано с предметом обсуждения.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Feb 28 2014, 02:32
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(AHTOXA @ Feb 27 2014, 21:00)  При том, что мы с вами вели речь про оператор BL. Помните, я вам объяснял, как он работает? Так вот. Оператор BL - это вызов функции. Поэтому я и пишу про вызов функции. Напомню также, что у juvf речь шла о вызове перегруженного оператора. А это - тоже вызов функции. Вот только не надо передёргивать! Тут есть история и всегда можно посмотреть о чём и когда шла речь. Во-первых - вызов перегруженного члена класса не может осуществляться BL, а только командами BLX; BX; LDR PC, ...; (возможно ещё TBB/TBH) - почитайте последние сообщения тут, чтобы понять почему. Во-вторых - речь тут не шла о вызове функции. Это вы не понятно почему решили, что уход исполнения по неверному адресу почему-то должен осуществляться именно по BL. А я вам напомнил о других командах передачи управления (причём - с косвенной адресацией). И непонятно почему вы решили, что значение в LR как-то связано с местом возникновения fault-а, хотя там просто может быть адрес возврата из последней когда-то вызванной функции (никак не связанный с местом текущего выполнения и fault-a) или вообще случайные данные (если после последнего BL/BLX регистр LR использовался как РОН). И ещё раз повторю если вы не поняли - по BL в принципе не может быть передачи управления по случайному адресу (если конечно нет ошибок компоновки и код не компонуется для работы в ОЗУ) так как адрес перехода (смещение) находится в коде команды (во флеш). Цитата(AHTOXA @ Feb 27 2014, 21:00)  Я знаю много разных команд. А ещё я знаю стихи Маяковского. Но ни то ни другое не связано с предметом обсуждения. Предмет обсуждения был - HardFault из-за выполнения данных как кода. И размышлений как туда попали. А попасть туда могли по любой команде передачи управления с косвенной адресацией, например одной из приведённых мной. А не только по BLX как вы почему-то решили. Например - любой случай разрушения стека (из-за его переполнения, или выхода указателя за пределы массива на стеке и т.п.) мог привести к выборке неверного адреса и перехода по нему по команде POP {PC}. При этом LR может продолжать указывать на какой-то адрес возврата из когда вызванной функции непонятно где в месте никак не относящемся к адресу fault-а.
|
|
|
|
|
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 должна прыгать на код вашего перегруженного оператора, а вместо этого прыгает в ОЗУ. Да, похоже, что память портится. И тут, как чёрт из табакерки, выскочили вы, и начали умничать. Я бы уже давно перестал отвечать на ваши петушиные наскоки, но всё надеялся, что вы перечитаете тему, переосмыслите и признаете свою неправоту. Однако теперь вижу, что это бесполезно. Думаю, что в этом ответе я предельно чётко подытожил описание проблемы и её решение. Надеюсь, это поможет кому-то, кто будет читать эту тему потом. Что касаемо дальнейшей дискуссии с вами, то я не вижу в ней никакого смысла.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
Сообщений в этой теме
klen Hard Fault Exception на кортексе м3 Feb 4 2010, 10:37 klen проблему я пофиксил - SNTP клиент косячил. все пре... Feb 4 2010, 17:12 AHTOXA Вот так у меня сработало:
Кодvoid hard_fault_hand... Feb 5 2010, 11:23  klen очень хорошо будем смотреть в "бубен около ко... Feb 5 2010, 14:45   AHTOXA Цитата(klen @ Feb 5 2010, 19:45) только с... Feb 5 2010, 14:58    klen уря уря уря!!!
naked действительно во ... Feb 5 2010, 15:23     Сергей Борщ Цитата(jcxz @ Feb 27 2014, 08:09) Адрес в... Feb 27 2014, 06:56      jcxz Функции как вызываются? Правильно: обычно через BL... Feb 27 2014, 07:48       Сергей Борщ Цитата(jcxz @ Feb 27 2014, 09:48) BL что ... Feb 27 2014, 09:51        jcxz Цитата(Сергей Борщ @ Feb 27 2014, 15:51) ... Feb 27 2014, 11:42         juvf Цитата(jcxz @ Feb 27 2014, 16:51) если ад... Feb 27 2014, 12:05          jcxz Цитата(juvf @ Feb 27 2014, 18:05) ну адре... Feb 27 2014, 12:50           juvf Цитата(jcxz @ Feb 27 2014, 17:50) Если у ... Feb 27 2014, 13:03 juvf спасибо.
перед 0x8002c09 такой код
КодLDR R1, ... Feb 26 2014, 12:28 AHTOXA Цитата(juvf @ Feb 26 2014, 18:28) перед 0... Feb 26 2014, 12:54 Axel Цитата(juvf @ Feb 26 2014, 16:28) Подозре... Feb 26 2014, 14:00 MALLOY2 Если это иар и используется его алокатор, то вам h... Feb 26 2014, 12:47 ViKo При прерываниях адрес возврата сохраняется в стек ... Feb 27 2014, 05:51 juvf Думаю, что я нашел граблю. я в одном потоке делаю ... Feb 27 2014, 11:48 juvf Давайте жить дружно Feb 28 2014, 09:14 juvf stm32L052 падает в HF
пытаюсь сделать обработчик ... Mar 30 2017, 15:27 AHTOXA Цитата(juvf @ Mar 30 2017, 20:27) Error[O... Mar 30 2017, 16:10 jcxz Цитата(juvf @ Mar 30 2017, 17:27) препроц... Mar 30 2017, 17:03  juvf Цитата(jcxz @ Mar 30 2017, 22:03) Препроц... Mar 31 2017, 03:34 Obam А что, на брейкпойнте в точке входа в HF и под JTA... Mar 31 2017, 07:46 juvf Цитата(Obam @ Mar 31 2017, 12:46) А что, ... Mar 31 2017, 08:30  Шаманъ Цитата(juvf @ Mar 31 2017, 11:30) По мойм... Mar 31 2017, 09:02   jcxz Цитата(Шаманъ @ Mar 31 2017, 11:02) Тогда... Mar 31 2017, 09:13    Forger Цитата(jcxz @ Mar 31 2017, 12:13) Вот тут... Mar 31 2017, 09:17    ViKo Цитата(jcxz @ Mar 31 2017, 12:13) У Corte... Mar 31 2017, 09:32     jcxz Цитата(ViKo @ Mar 31 2017, 11:32) А не на... Mar 31 2017, 09:46      ViKo Цитата(jcxz @ Mar 31 2017, 12:46) Не обяз... Mar 31 2017, 10:07       jcxz Цитата(ViKo @ Mar 31 2017, 12:07) Этот вы... Mar 31 2017, 10:17      Шаманъ Цитата(jcxz @ Mar 31 2017, 12:46) Не обяз... Mar 31 2017, 10:31       jcxz Цитата(Шаманъ @ Mar 31 2017, 12:31) Вы пр... Mar 31 2017, 13:11        ViKo Цитата(jcxz @ Mar 31 2017, 16:11) Читайте... Mar 31 2017, 13:37         jcxz Цитата(ViKo @ Mar 31 2017, 15:37) Только ... Mar 31 2017, 14:34       Forger Цитата(Шаманъ @ Mar 31 2017, 13:31) Но, п... Mar 31 2017, 13:39    Шаманъ Цитата(jcxz @ Mar 31 2017, 12:13) У Corte... Mar 31 2017, 09:38 ViKo Можно. Только, когда ошибка появляется в рабочем п... Mar 31 2017, 08:14 Forger Цитата(ViKo @ Mar 31 2017, 11:14) Можно. ... Mar 31 2017, 09:08 Obam "…в рабочем приборе, вдалеке от отладчика…... Mar 31 2017, 08:26 ViKo Цитата(Obam @ Mar 31 2017, 11:26) "…... Mar 31 2017, 08:38 ViKo Будем считать, что мне везло, и я всегда попадал и... Mar 31 2017, 10:34 Шаманъ Цитата(jcxz @ Mar 31 2017, 16:11) Читайте... Mar 31 2017, 14:01 Forger Цитата(Шаманъ @ Mar 31 2017, 17:01) Я обы... Mar 31 2017, 14:11  Шаманъ Цитата(Forger @ Mar 31 2017, 17:11) А я п... Mar 31 2017, 14:35   Forger Цитата(Шаманъ @ Mar 31 2017, 17:35) Но ра... Mar 31 2017, 15:04    Шаманъ Цитата(Forger @ Mar 31 2017, 18:04) Честн... Mar 31 2017, 16:08     Forger Цитата(Шаманъ @ Mar 31 2017, 19:08) У мен... Mar 31 2017, 16:28      Шаманъ Цитата(Forger @ Mar 31 2017, 19:28) Потом... Mar 31 2017, 17:16       Forger Цитата(Шаманъ @ Mar 31 2017, 20:16) В кон... Mar 31 2017, 18:05
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|