|
|
  |
Hard Fault Exception на кортексе м3, как узнать откуда прилезло |
|
|
|
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, 12:50
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(juvf @ Feb 27 2014, 18:05)  ну адрес оператора MyClass::operator--() находится в озу. точнее не сам оператор, а только его адрес. сам оператор конечно же во флешь. но дело в том, что объект класса MyClass создан динамически в куче. И соответственно в озу лежит таблица с указателями на методы этого класса. Не факт. Это очень неэффективно - тратить кучу ОЗУ, сохраняя таблицу указателей на методы для каждого объекта в ОЗУ. Если у вас имеется класс с перегруженными функциями, то для каждого такого класса компилятор скорей всего создаёт таблицу член-функций и сохраняет её во флеш. А в самом объекте класса хранит только адрес такой таблицы. Хотя тут конечно от компилятора зависит, но в embedded-области ОЗУ - очень ценный ресурс.
|
|
|
|
|
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-а.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|