реклама на сайте
подробности

 
 
> Hard Fault Exception на кортексе м3, как узнать откуда прилезло
klen
сообщение Feb 4 2010, 10:37
Сообщение #1


бессмертным стать можно тремя способами
*****

Группа: Свой
Сообщений: 1 405
Регистрация: 9-05-06
Из: Москва
Пользователь №: 16 912



Здравствуйте.
работает программа на stm32f107 uIP+DHCP+HTTPD+TELNETD.

все просто замечательно работает, но не долго - минуту, через примерно одинаковый интервал времени - systick показывает очень близкие значения, все вываливается в HardFaultException с вероятностью 1. видимо гдето чето кончаетсо, буфер например. пытаюсь понять.

как высчитать в обработчике адрес с которого все это прилитело?

нагугленная конструкция
asm volatile ("MRS R0,PSP") ;
asm volatile ("LDR R1,[R0,#24] \n");
выдает чето мне непонятное.

спасибо.
Go to the top of the page
 
+Quote Post
5 страниц V   1 2 3 > »   
Start new topic
Ответов (1 - 64)
klen
сообщение Feb 4 2010, 17:12
Сообщение #2


бессмертным стать можно тремя способами
*****

Группа: Свой
Сообщений: 1 405
Регистрация: 9-05-06
Из: Москва
Пользователь №: 16 912



проблему я пофиксил - SNTP клиент косячил. все прекрасно заработато.

но вопрос то отался - как в обработчике исключительной ситуации Hard Fault получить адрес инструкции котороая привела к эксепшену? Ну вопрос то наверно простой, гдето ячето неправильно даташит понимаю.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Feb 5 2010, 11:23
Сообщение #3


фанат дивана
******

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



Вот так у меня сработало:

Код
void hard_fault_handler(unsigned int * hardfault_args)
{
    rs_puts("\r\nhard_fault_handler!\r\nPC=");
    rs_put_hex(hardfault_args[6]);
    for(;;);
}

void HardFault_Handler(void) __attribute__ (( naked ));

// собственно обработчик
void HardFault_Handler(void)
{
    asm volatile (
        "TST LR, #4              \n"
        "ITE EQ                    \n"
        "MRSEQ R0, MSP        \n"
        "MRSNE R0, PSP         \n"
        "B hard_fault_handler    "
    );
}

//Проверка:
void test1()
{
    __asm volatile
    (
        "MOVS r0, #1         \n"
        "LDM r0,{r1-r2}        \n"
        "BX LR                \n"
    );
}


Вывод в UART почему-то не сработал, но в отладчике видно, что в hardfault_args[6] - адрес строчки ldmia.w r0, {r1, r2}.

Взято отсюда.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
klen
сообщение Feb 5 2010, 14:45
Сообщение #4


бессмертным стать можно тремя способами
*****

Группа: Свой
Сообщений: 1 405
Регистрация: 9-05-06
Из: Москва
Пользователь №: 16 912



очень хорошо будем смотреть в "бубен около костра"

только с ходу вроде бы то что я вставлял
asm volatile ("MRS R0,PSP") ;
asm volatile ("LDR R1,[R0,#24]");
почти тоже самое? что Вы привели, - выдавало в r1 бред.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Feb 5 2010, 14:58
Сообщение #5


фанат дивана
******

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



Цитата(klen @ Feb 5 2010, 19:45) *
только с ходу вроде бы то что я вставлял
asm volatile ("MRS R0,PSP") ;
asm volatile ("LDR R1,[R0,#24]");
почти тоже самое? что Вы привели, - выдавало в r1 бред.


Почтиsmile.gif Во-первых, там идёт выбор между PSP и MSP. Может не угадали. И, во-вторых (я забыл это указать), используется naked HardFault_Handler - чтоб не портить указатель стека.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
klen
сообщение Feb 5 2010, 15:23
Сообщение #6


бессмертным стать можно тремя способами
*****

Группа: Свой
Сообщений: 1 405
Регистрация: 9-05-06
Из: Москва
Пользователь №: 16 912



yeah.gif
уря уря уря!!!
naked действительно во вторых!! потому что во первых я тупой - не обратилвнимание на то что стек пересчитывается......
все остально включая асм - ничего ценного, к вопросу топика ценны тока "во первых" и "во вторых" в моей нумерации.

спасибо. я б еще наверно долго тупил бы и искал проблему совершенно в другом месте.
ну вот, еще одно подтверждление того что простые загадки имеюют простые решения но очень сложный "этого решения" процесс
Go to the top of the page
 
+Quote Post
juvf
сообщение Feb 25 2014, 18:54
Сообщение #7


Профессионал
*****

Группа: Свой
Сообщений: 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
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Feb 26 2014, 11:30
Сообщение #8


фанат дивана
******

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



Судя по
Цитата(juvf @ Feb 26 2014, 00:54) *
LR = 0x8002c09
PC = 0x20001498

, при возникновении исключения выполнялся код в ОЗУ (0x20001498). Посмотрите команду, которая находится перед 0x8002c08, возможно дело в ней.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
juvf
сообщение Feb 26 2014, 12:28
Сообщение #9


Профессионал
*****

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



спасибо.

перед 0x8002c09 такой код

Код
LDR R1, [R1]
LDR R1,[R1, #0x8]
BLX R1
CMP R0,#0

по адресу 0x8002c08 команда CMP R0,#0. Зметил ещё что как раз в R1 = 0x20001498

в стеке есть список классов созданный через new. от сюда и рс на кучу кажет. падает в перегруженном операторе --

if(--(*(MyClass*)p) )
{
}

ошибки в операторе -- нет. указатель р всегда указывает на нужное место (есди его только не портят в паралельном месте). Если увеличиваю в линкере кучу с 0х400 до 0х600, то больше HF не наблюдаю. Подозрене что не хватает кучи. Как это проверить?
Go to the top of the page
 
+Quote Post
MALLOY2
сообщение Feb 26 2014, 12:47
Сообщение #10


Знающий
****

Группа: Validating
Сообщений: 838
Регистрация: 31-01-05
Пользователь №: 2 317



Если это иар и используется его алокатор, то вам http://supp.iar.com/Support/?note=28545
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Feb 26 2014, 12:54
Сообщение #11


фанат дивана
******

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



Цитата(juvf @ Feb 26 2014, 18:28) *
перед 0x8002c09 такой код

Код
LDR R1, [R1]
LDR R1,[R1, #0x8]
BLX R1
CMP R0,#0

Команда BLX R1 должна прыгать на код вашего перегруженного оператора, а вместо этого прыгает в ОЗУ. Да, похоже, что память портится.
Как посмотреть переполнение кучи в ИАРе - не знаю, не пользуюсь им.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
Axel
сообщение Feb 26 2014, 14:00
Сообщение #12


Местный
***

Группа: Свой
Сообщений: 480
Регистрация: 21-11-04
Пользователь №: 1 188



Цитата(juvf @ Feb 26 2014, 16:28) *
Подозрене что не хватает кучи. Как это проверить?


Да вроде бы несложно. После каждого вызова new (или malloc) сравнивать выделенный адрес с ранее полученными и запоминать максимальный, а в обработчике посмотреть, что получилось. Или, если есть что-нибудь типа debug_printf (IARом не пользуюсь, поэтому не знаю) - печатать в окне дебагера.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Feb 27 2014, 02:20
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 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 таких дампов в ОЗУ. При наступлении сбоя - смотрел последовательность этих дампов и определял где
было последнее валидное состояние. Расстояние между такими дампами получалось всего несколько десятков команд - место сбоя ловилось довольно точно.

Ну или нужен какой-то аппаратный трэйсер с запоминанием потока команд и возможностью отмотать назад.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Feb 27 2014, 05:21
Сообщение #14


фанат дивана
******

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



Цитата(jcxz @ Feb 27 2014, 08:20) *
Почему Вы решили, что в LR - адрес возврата из функции, в которой произошло исключение? Имхо - там может быть что угодно.

Потому что обычно там находится адрес возвратаsm.gif И обычно компилятор использует 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.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
ViKo
сообщение Feb 27 2014, 05:51
Сообщение #15


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



При прерываниях адрес возврата сохраняется в стек (там его можно и найти, положение известно). А в LR заносится специальное слово EXC_RETURN (там почти одни единицы).
Go to the top of the page
 
+Quote Post
jcxz
сообщение Feb 27 2014, 06:09
Сообщение #16


Гуру
******

Группа: Свой
Сообщений: 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.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Feb 27 2014, 06:56
Сообщение #17


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(jcxz @ Feb 27 2014, 08:09) *
Адрес возврата в LR внутри функции хранится только если в функции нет вложенных вызовов других функций. Подумайте почему.
Почему? PUSH LR уже изменяет содержимое LR?


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
jcxz
сообщение Feb 27 2014, 07:48
Сообщение #18


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Функции как вызываются? Правильно: обычно через BL.
BL что делает с LR?
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Feb 27 2014, 08:46
Сообщение #19


фанат дивана
******

Группа: Свой
Сообщений: 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 находится адрес возвратаsm.gif

И ещё одно соображение. Если HardFault вызван переходом по несуществующему адресу (а это как раз случай, о котором спрашивал juvf), то LR содержит адрес возврата гарантированно, поскольку по несуществующему адресу нет кода, который может "сохранить на стек LR и использовать его для каких-то других целей".


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
jcxz
сообщение Feb 27 2014, 09:11
Сообщение #20


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(AHTOXA @ Feb 27 2014, 14:46) *
Судя по ней, вы не знаете как работает BL.

Из чего вы сделали такой вывод? Что же там по вашему в LR???

Цитата(AHTOXA @ Feb 27 2014, 14:46) *
Ну вот и посмотрите на свой пример. Более половины времени выполнения функции в LR находится адрес возвратаsm.gif

Каким образом интересно вы вычислили время выполнения и размер функции???
И причём это тут вообще?

Цитата(AHTOXA @ Feb 27 2014, 14:46) *
И ещё одно соображение. Если HardFault вызван переходом по несуществующему адресу (а это как раз случай, о котором спрашивал juvf), то LR содержит адрес возврата гарантированно, поскольку по несуществующему адресу нет кода, который может "сохранить на стек LR и использовать его для каких-то других целей".

И что? С чего вы решили что до перехода там содержался адрес возврата???

PS: Блин - вместо того чтобы тут нести чушь, почитайте лучше описание системы команд!
Большего количества чуши в одном сообщении трудно найти....
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Feb 27 2014, 09:51
Сообщение #21


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(jcxz @ Feb 27 2014, 09:48) *
BL что делает с LR?
Уже даже боюсь спросить, что же BL делает с LR? Всегда думал, что записывает в него... (ужас!) адрес возврата.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Feb 27 2014, 10:54
Сообщение #22


фанат дивана
******

Группа: Свой
Сообщений: 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: Блин - вместо того чтобы тут нести чушь, почитайте лучше описание системы команд!
Большего количества чуши в одном сообщении трудно найти....



--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
jcxz
сообщение Feb 27 2014, 11:42
Сообщение #23


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Сергей Борщ @ Feb 27 2014, 15:51) *
Уже даже боюсь спросить, что же BL делает с LR? Всегда думал, что записывает в него... (ужас!) адрес возврата.

Теперь ещё немного дальше подумайте - что будет если внутри 1-й функции будет вызов 2-й функции? А если ещё дальше - в функции2 вызов функции3?
Что будет в LR после всего этого?
Go to the top of the page
 
+Quote Post
juvf
сообщение Feb 27 2014, 11:48
Сообщение #24


Профессионал
*****

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



Думаю, что я нашел граблю. я в одном потоке делаю if(--(*(MyClass*)p) ), а в дркгом потоке

....
delete p;
p = new MyClass(...);
...

иногда, оператор -- выполняется между delete и new.

Всем спасибо за помощь!
Go to the top of the page
 
+Quote Post
jcxz
сообщение Feb 27 2014, 11:51
Сообщение #25


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(AHTOXA @ Feb 27 2014, 16:54) *
Потому что так в кортексах происходит вызов функций - командой BL.

Причём тут "вызов функций"??
Вы пишете переходом по несуществующему адресу.
Неужто такие переходы могут быть только по команде BL?
Может тогда просто - удалить её нафик из системы команд и не будет проблем? wink.gif
А как же всякие BX Rx, POP {PC}, LDR PC, ... и пр.? Вы такие команды знаете?
И что происходит при нехватке стека? Уж-ли не из-за POP {PC} за пределами стека может вызвать
переход по несуществующему адресу?
И как интересно команда BL addr может вызвать переход по несуществующему адресу,
если адрес перехода находится в теле самой команды, которая скорее всего находится во FLASH и этот адрес формирует линкёр???
Go to the top of the page
 
+Quote Post
juvf
сообщение Feb 27 2014, 12:05
Сообщение #26


Профессионал
*****

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



Цитата(jcxz @ Feb 27 2014, 16:51) *
если адрес перехода находится в теле самой команды, которая скорее всего находится во FLASH и этот адрес формирует линкёр???

эээ..... может я инфы мало дал.... сори...

ну адрес оператора MyClass::operator--() находится в озу. точнее не сам оператор, а только его адрес. сам оператор конечно же во флешь. но дело в том, что объект класса MyClass создан динамически в куче. И соответственно в озу лежит таблица с указателями на методы этого класса.
Если объект удален, и сделать по пустому указателю вызов метода, как раз процессор полезит в озу, чтобы получить адресс нужного метода, а потом по этому адресу сделает переход. и далее куда там попало..... там может до HF выполниться ещё несколько команд.

Go to the top of the page
 
+Quote Post
jcxz
сообщение Feb 27 2014, 12:50
Сообщение #27


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(juvf @ Feb 27 2014, 18:05) *
ну адрес оператора MyClass::operator--() находится в озу. точнее не сам оператор, а только его адрес. сам оператор конечно же во флешь. но дело в том, что объект класса MyClass создан динамически в куче. И соответственно в озу лежит таблица с указателями на методы этого класса.

Не факт. Это очень неэффективно - тратить кучу ОЗУ, сохраняя таблицу указателей на методы для каждого объекта в ОЗУ.
Если у вас имеется класс с перегруженными функциями, то для каждого такого класса компилятор скорей всего создаёт таблицу член-функций и сохраняет её во флеш.
А в самом объекте класса хранит только адрес такой таблицы.
Хотя тут конечно от компилятора зависит, но в embedded-области ОЗУ - очень ценный ресурс.
Go to the top of the page
 
+Quote Post
juvf
сообщение Feb 27 2014, 13:03
Сообщение #28


Профессионал
*****

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



Цитата(jcxz @ Feb 27 2014, 17:50) *
Если у вас имеется класс с перегруженными функциями, то для каждого такого класса компилятор скорей всего создаёт таблицу член-функций и сохраняет её во флеш.
А в самом объекте класса хранит только адрес такой таблицы.
Хотя тут конечно от компилятора зависит, но в embedded-области ОЗУ - очень ценный ресурс.

Да, всё верно. В озу храниться только указатель на таблицу указателей. Но тем не менее, после delete .... обращение по указателю... можно получить неправильный указатель из озу на таблицу указателей во флешь, ну и неправильный переход. В том числе PC может перескочить на озу и выполится какая нибудь команда из озу.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Feb 27 2014, 15:00
Сообщение #29


фанат дивана
******

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



Цитата(juvf @ Feb 27 2014, 17:48) *
Думаю, что я нашел граблю.

Аминь! sm.gif

Цитата(jcxz @ Feb 27 2014, 17:51) *
Причём тут "вызов функций"??

При том, что мы с вами вели речь про оператор BL. Помните, я вам объяснял, как он работает? Так вот. Оператор BL - это вызов функции. Поэтому я и пишу про вызов функции.
Напомню также, что у juvf речь шла о вызове перегруженного оператора. А это - тоже вызов функции.

Цитата(jcxz @ Feb 27 2014, 17:51) *
Вы пишете переходом по несуществующему адресу.
Неужто такие переходы могут быть только по команде BL?

Переходы, вызванные вызовом функции - да.
Цитата(jcxz @ Feb 27 2014, 17:51) *
Может тогда просто - удалить её нафик из системы команд и не будет проблем? wink.gif
А как же всякие BX Rx, POP {PC}, LDR PC, ... и пр.? Вы такие команды знаете?

Я знаю много разных команд. А ещё я знаю стихи Маяковского. Но ни то ни другое не связано с предметом обсуждения.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
jcxz
сообщение Feb 28 2014, 02:32
Сообщение #30


Гуру
******

Группа: Свой
Сообщений: 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-а.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Feb 28 2014, 04:36
Сообщение #31


фанат дивана
******

Группа: Свой
Сообщений: 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 должна прыгать на код вашего перегруженного оператора, а вместо этого прыгает в ОЗУ. Да, похоже, что память портится.


И тут, как чёрт из табакерки, выскочили вы, и начали умничать. Я бы уже давно перестал отвечать на ваши петушиные наскоки, но всё надеялся, что вы перечитаете тему, переосмыслите и признаете свою неправоту. Однако теперь вижу, что это бесполезно. Думаю, что в этом ответе я предельно чётко подытожил описание проблемы и её решение. Надеюсь, это поможет кому-то, кто будет читать эту тему потом. Что касаемо дальнейшей дискуссии с вами, то я не вижу в ней никакого смысла.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
jcxz
сообщение Feb 28 2014, 05:59
Сообщение #32


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Я с вами тоже sm.gif
Go to the top of the page
 
+Quote Post
juvf
сообщение Feb 28 2014, 09:14
Сообщение #33


Профессионал
*****

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



Давайте жить дружно beer.gif
Go to the top of the page
 
+Quote Post
juvf
сообщение Mar 30 2017, 15:27
Сообщение #34


Профессионал
*****

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



stm32L052 падает в 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?
Эскизы прикрепленных изображений
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Mar 30 2017, 16:10
Сообщение #35


фанат дивана
******

Группа: Свой
Сообщений: 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-а сами подправьте).


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
jcxz
сообщение Mar 30 2017, 17:03
Сообщение #36


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(juvf @ Mar 30 2017, 17:27) *
препроцессор в режиме Thumb.

Препроцессор только в одном режиме может работать - в режиме си.
Go to the top of the page
 
+Quote Post
juvf
сообщение Mar 31 2017, 03:34
Сообщение #37


Профессионал
*****

Группа: Свой
Сообщений: 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 */
}
Go to the top of the page
 
+Quote Post
Obam
сообщение Mar 31 2017, 07:46
Сообщение #38


Знающий
****

Группа: Участник
Сообщений: 756
Регистрация: 14-11-14
Пользователь №: 83 663



А что, на брейкпойнте в точке входа в HF и под JTAGом, нельзя посмотреть содержимое регистров без портянки из printf-ов?
Просто интересуюсь…


--------------------
Пролетарий умственного труда.
Go to the top of the page
 
+Quote Post
ViKo
сообщение Mar 31 2017, 08:14
Сообщение #39


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Можно. Только, когда ошибка появляется в рабочем приборе, вдалеке от отладчика, вот тогда нужно пересылать информацию.
Go to the top of the page
 
+Quote Post
Obam
сообщение Mar 31 2017, 08:26
Сообщение #40


Знающий
****

Группа: Участник
Сообщений: 756
Регистрация: 14-11-14
Пользователь №: 83 663



"…в рабочем приборе, вдалеке от отладчика…"
Тогда тут то, чем зебра заканчивается… дистанционно добавлять в прошивку диагностику HF sad.gif


--------------------
Пролетарий умственного труда.
Go to the top of the page
 
+Quote Post
juvf
сообщение Mar 31 2017, 08:30
Сообщение #41


Профессионал
*****

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



Цитата(Obam @ Mar 31 2017, 12:46) *
А что, на брейкпойнте в точке входа в HF и под JTAGом, нельзя посмотреть содержимое регистров без портянки из printf-ов?
Просто интересуюсь…
По мойму нельзя.
Go to the top of the page
 
+Quote Post
ViKo
сообщение Mar 31 2017, 08:38
Сообщение #42


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(Obam @ Mar 31 2017, 11:26) *
"…в рабочем приборе, вдалеке от отладчика…"
Тогда тут то, чем зебра заканчивается… дистанционно добавлять в прошивку диагностику HF sad.gif

Программа выдала симптомы, а диагноз выполняет и лечение назначает программист, глядя в исходник сотворенного.
Go to the top of the page
 
+Quote Post
Шаманъ
сообщение Mar 31 2017, 09:02
Сообщение #43


Знающий
****

Группа: Участник
Сообщений: 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, выйдет как раз в место его возникновения, бывает очень удобно. Можно конечно адрес из стека вытащить, но так проще, удобней, нагляднее.
Go to the top of the page
 
+Quote Post
Forger
сообщение Mar 31 2017, 09:08
Сообщение #44


Профессионал
*****

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



Цитата(ViKo @ Mar 31 2017, 11:14) *
Можно. Только, когда ошибка появляется в рабочем приборе, вдалеке от отладчика, вот тогда нужно пересылать информацию.

Все HF следует отлавливать еще на этапе отладки и прогона на месте, иначе грош-цена такому коду.
А вот для фиксации различных событий и т. п. следует использовать самописный или готовый журнал событий, который писать на внешнюю или внутр. флэшку.
В этом случае можно спокойно проанализировать записи в журнале за некий период работы, просто переслав разработчику соотв. файл журнала событий.
Для этого никуда ездить не нужно.
Если есть доступ в сеть, то можно научить девайс писать журнал сразу наружу, да хоть на "облако" ))


--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
Go to the top of the page
 
+Quote Post
jcxz
сообщение Mar 31 2017, 09:13
Сообщение #45


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Шаманъ @ Mar 31 2017, 11:02) *
Тогда можно переменную i в отладчике поменять на 0 и пройтись до выхода из HardFault, выйдет как раз в место его возникновения, бывает очень удобно. Можно конечно адрес из стека вытащить, но так проще, удобней, нагляднее.

У Cortex есть неточные ошибки с памятью (Imprecise Bus Fault). Так Вы их место не найдёте. А через регистры - найдёте.
Да и очень неудобно каждый раз вспоминать где какой стек, лучше иметь готовый код.
Не зря же даже в винде подобный обработчик сделали с регистрами и стеком (синий экран). Вот у меня как раз подобный для Cortex есть wink.gif

Цитата(Forger @ Mar 31 2017, 11:08) *
Все HF следует отлавливать еще на этапе отладки и прогона на месте, иначе грош-цена такому коду.
А вот для фиксации различных событий и т. п. следует использовать самописный или готовый журнал событий, который писать на внешнюю или внутр. флэшку.

Это конечно всё хорошо и правильно. Но на практике почему-то случаются такие ошибки (в том числе и HF), которые проявляются почему-то только у заказчика laughing.gif
Вот тут-то фиксация в журнал спасает (а особенно - в энергонезависимый).
Go to the top of the page
 
+Quote Post
Forger
сообщение Mar 31 2017, 09:17
Сообщение #46


Профессионал
*****

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



Цитата(jcxz @ Mar 31 2017, 12:13) *
Вот тут-то фиксация в журнал спасает (а особенно - в энергонезависимый).

А разве кому-то нужен энергозависимый журнал?


--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
Go to the top of the page
 
+Quote Post
ViKo
сообщение Mar 31 2017, 09:32
Сообщение #47


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(jcxz @ Mar 31 2017, 12:13) *
У Cortex есть неточные ошибки с памятью (Imprecise Bus Fault). Так Вы их место не найдёте. А через регистры - найдёте.
Да и очень неудобно каждый раз вспоминать где какой стек, лучше иметь готовый код.

А не надо думать про стек. При шаге - возврате из обработчика - попадете туда, откуда упали.

Цитата(jcxz @ Mar 31 2017, 12:13) *
Но на практике почему-то случаются такие ошибки (в том числе и HF), которые проявляются почему-то только у заказчика laughing.gif

Летом было. На скорую руку поправил одну функцию, типа, улучшил, по требованию. Проверил - работает, да и забыл про нее. Отправили 10 приборов в Нижний Новгород. Там они все "зависли намертво". Вернулись назад. Причину нашел быстро. Если бы там были лучшие умельцы, могли бы обновить программу сами. Но таковых не оказалось. Я уже заподозрил в попытке взлома... biggrin.gif
Go to the top of the page
 
+Quote Post
Шаманъ
сообщение Mar 31 2017, 09:38
Сообщение #48


Знающий
****

Группа: Участник
Сообщений: 758
Регистрация: 27-08-08
Пользователь №: 39 839



Цитата(jcxz @ Mar 31 2017, 12:13) *
У Cortex есть неточные ошибки с памятью (Imprecise Bus Fault). Так Вы их место не найдёте. А через регистры - найдёте.

Я не противопоставлял такой вариант обработчика просмотру содержимого регистров - скорее одно дополняет другое. Вывалились в обработчик посмотрели регистры, вернулись обратно (так сказать с комфортом) и посмотрели как содержимое регистров использовалось в момент вылета. Вот собственно и все.

Цитата
Да и очень неудобно каждый раз вспоминать где какой стек, лучше иметь готовый код.

ViKo уже ответил, все произойдет само - вернетесь туда откуда выпали, вне зависимости от используемого стека.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Mar 31 2017, 09:46
Сообщение #49


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(ViKo @ Mar 31 2017, 11:32) *
А не надо думать про стек. При шаге - возврате из обработчика - попадете туда, откуда упали.

Не обязательно. Прочитайте про неточные ошибки с памятью. Fault может произойти через несколько команд после места ошибки. Когда уже может выполняться другая функция или даже другая задача ОС или ISR. Возвращаетесь так по LR, а в том месте даже команд обращения к памяти вообще нет. wink.gif

Цитата(ViKo @ Mar 31 2017, 11:32) *
Вернулись назад. Причину нашел быстро. Если бы там были лучшие умельцы, могли бы обновить программу сами. Но таковых не оказалось. Я уже заподозрил в попытке взлома... biggrin.gif

Надо делать удалённое обновление.

Цитата(Шаманъ @ Mar 31 2017, 11:38) *
ViKo уже ответил, все произойдет само - вернетесь туда откуда выпали, вне зависимости от используемого стека.

И Вам тоже - читать мануал на ядро Cortex-M. Плюс - набраться опыта в отладке и ловле fault-ов.
Или тут все только с Cortex-M0 работают где нет кешей и буферов отложенной записи и т.п.? Ну так и это ненадолго. cool.gif
Go to the top of the page
 
+Quote Post
ViKo
сообщение Mar 31 2017, 10:07
Сообщение #50


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(jcxz @ Mar 31 2017, 12:46) *
Не обязательно. Прочитайте про неточные ошибки с памятью. Fault может произойти через несколько команд после места ошибки. Когда уже может выполняться другая функция или даже другая задача ОС или ISR. Возвращаетесь так по LR, а в том месте даже команд обращения к памяти вообще нет. wink.gif

Этот выход указывает, в какой функции глюк. А дальше я уже по исходнику смотрю, что там может быть не так.
Цитата
Надо делать удалённое обновление.

Ну, как бы, заложено. Но пользователи на том конце должны уметь кабель к компу подключить и прошивку по нему послать.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Mar 31 2017, 10:17
Сообщение #51


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(ViKo @ Mar 31 2017, 12:07) *
Этот выход указывает, в какой функции глюк. А дальше я уже по исходнику смотрю, что там может быть не так.

да ну? sm.gif
Вот Вы видите что выход произошёл на:
MOVS R0, #1
ADDS R1, #2
LSLS R1, R1, #1
ITT MI
MOVSMI R2,#1
MOVSMI R3,#2
...
и ещё пару десятков подобных команд до этого. И где же глюк? Даже ни одного обращения к памяти нету. cool.gif
А глюк оказывается был вообще в другой задаче, из которой управление только, что было передано сюда (например - переполнение её стека, запись в несуществующую/запрещённую память как раз в момент сохранения контекста, которая из-за наличия отложенной записи выдала Imprecise Bus Fault).
Или он вообще был в ISR, который только что завершился BX LR.
Или наоборот - это код в ISR, который только что прервал задачу, в которой и произошёл данный сбой.
И где точно - Вы не знаете так как неточная ошибка памяти она на то и неточная - что где-то за несколько команд или десяток команд ранее случилась до входа в fault.
Go to the top of the page
 
+Quote Post
Шаманъ
сообщение Mar 31 2017, 10:31
Сообщение #52


Знающий
****

Группа: Участник
Сообщений: 758
Регистрация: 27-08-08
Пользователь №: 39 839



Цитата(jcxz @ Mar 31 2017, 12:46) *
Не обязательно. Прочитайте про неточные ошибки с памятью. Fault может произойти через несколько команд после места ошибки. Когда уже может выполняться другая функция или даже другая задача ОС или ISR. Возвращаетесь так по LR, а в том месте даже команд обращения к памяти вообще нет. wink.gif
И Вам тоже - читать мануал на ядро Cortex-M. Плюс - набраться опыта в отладке и ловле fault-ов.
Или тут все только с Cortex-M0 работают где нет кешей и буферов отложенной записи и т.п.? Ну так и это ненадолго. cool.gif

Вы претендуете на наличие у Вас универсального решения? Так сказали "а", говорите "б" - рассказывайте, чтобы и кэши учитывались и несколько комманд и т.д., или Вы чисто поговорить?

Я на наличие универсального решения не претендовал. 99% разных fault отлавливаются приведенным выше алгоритмом. Если fault произошел не в той команде куда возвратились смотрим, что было до нее. Если совсем туго, то смотрим в регистр BFSR, оттуда можно почерпнуть полезной инфы в том числе произошла ли ошибка по адресу возврата или нет. Ну и если так ничего и не понятно через регистр ACTLR можно поотключать разные улучшатели и сделать из М7 почти что М0 wink.gif

Но, по моему опыту (М3/М7) обычно все отлавливается после возврата простым анализом 5..10 комманд до точки возврата.
Go to the top of the page
 
+Quote Post
ViKo
сообщение Mar 31 2017, 10:34
Сообщение #53


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Будем считать, что мне везло, и я всегда попадал именно в ту функцию, которая вызвала HF. rolleyes.gif (кэшей не было, точно)
А что вы найдете в этом случае через регистры, как писали выше?
Go to the top of the page
 
+Quote Post
jcxz
сообщение Mar 31 2017, 13:11
Сообщение #54


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Шаманъ @ Mar 31 2017, 12:31) *
Вы претендуете на наличие у Вас универсального решения? Так сказали "а", говорите "б" - рассказывайте, чтобы и кэши учитывались и несколько комманд и т.д., или Вы чисто поговорить?

Читайте выше. Из соответствующих регистров можно прочитать реальный адрес где произошёл fault.
Go to the top of the page
 
+Quote Post
ViKo
сообщение Mar 31 2017, 13:37
Сообщение #55


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(jcxz @ Mar 31 2017, 16:11) *
Читайте выше. Из соответствующих регистров можно прочитать реальный адрес где произошёл fault.

Только не в случае Imprecise Bus Fault, разве не так?
Go to the top of the page
 
+Quote Post
Forger
сообщение Mar 31 2017, 13:39
Сообщение #56


Профессионал
*****

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



Цитата(Шаманъ @ Mar 31 2017, 13:31) *
Но, по моему опыту (М3/М7) обычно все отлавливается после возврата простым анализом 5..10 комманд до точки возврата.

В подавляющем большинстве подобных случаев в этой злополучной строке будет обращение по указателю, особенно с приведением к другому типу. smile3046.gif
Например, как тут:
Код
if(--(*(MyClass*)p) )
Такой набор символов сходу и прочитать-то правильно сложно, а уж ошибиться - подавно ))

Короче, при HF первым делом нужно проверять (в порядке важности):
отсутствие любых предупреждений при компиляции (иногда даже стоит ужесточить условия их формирования), должно быть "Warinigs: 0"
объем стека/стеков и кучи,
конкурентный доступ к переменным из кода и прерываний (особое внимание обратить на глобальные переменные, которые используются в прерываниях),
все указатели, а особенно те, которые используются с приведением типа,
доступ к не инициализированным локальным переменным,
если есть RTOS и используются приоритеты прерываний, то убедится, что нет вызовов сервисов оси из обработчиков, приоритет прерываний которых выше значения, заданного в настройках оси (FreeRTOS),
ну и может еще что, с ходу не вспомню ))


--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
Go to the top of the page
 
+Quote Post
Шаманъ
сообщение Mar 31 2017, 14:01
Сообщение #57


Знающий
****

Группа: Участник
Сообщений: 758
Регистрация: 27-08-08
Пользователь №: 39 839



Цитата(jcxz @ Mar 31 2017, 16:11) *
Читайте выше. Из соответствующих регистров можно прочитать реальный адрес где произошёл fault.

В смысле мне себя почитать?
Цитата(Шаманъ @ Mar 31 2017, 12:38) *
Вывалились в обработчик посмотрели регистры, вернулись обратно (так сказать с комфортом) и посмотрели как содержимое регистров использовалось в момент вылета.

rolleyes.gif

Цитата(Forger @ Mar 31 2017, 16:39) *
В подавляющем большинстве подобных случаев в этой злополучной строке будет обращение по указателю, особенно с приведением к другому типу. smile3046.gif
Например, как тут:
Код
if(--(*(MyClass*)p) )

Я обычно в таких случаях смотрю ассемблерный код - это намного продуктивнее.
Go to the top of the page
 
+Quote Post
Forger
сообщение Mar 31 2017, 14:11
Сообщение #58


Профессионал
*****

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



Цитата(Шаманъ @ Mar 31 2017, 17:01) *
Я обычно в таких случаях смотрю ассемблерный код - это намного продуктивнее.

А я под словом "продуктивный" понимаю такой код, который вообще исключает всякую необходимость рыться в "белье" компилятора biggrin.gif

Сложные выражения предпочитаю разбить на примитивные, так и отлаживать проще.
Зачастую это в итоге вынуждает переписать код, отказавших от мудреных конструкций со "звездочками".
В итоге это экономит кучу времени, которое в ином случае было бы потрачено на поиск причин трудноуловимых багов.


--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
Go to the top of the page
 
+Quote Post
jcxz
сообщение Mar 31 2017, 14:34
Сообщение #59


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(ViKo @ Mar 31 2017, 15:37) *
Только не в случае Imprecise Bus Fault, разве не так?

Честно говоря - не помню уже. Обработчик fault-ов написал несколько лет назад. И забыл про эту проблему и какие конкретно регистры надо читать - он их сам читает и показывает когда надо. wink.gif
Go to the top of the page
 
+Quote Post
Шаманъ
сообщение Mar 31 2017, 14:35
Сообщение #60


Знающий
****

Группа: Участник
Сообщений: 758
Регистрация: 27-08-08
Пользователь №: 39 839



Цитата(Forger @ Mar 31 2017, 17:11) *
А я под словом "продуктивный" понимаю такой код, который вообще исключает всякую необходимость рыться в "белье" компилятора biggrin.gif

Я тоже за качественный и легко читаемый код - и в этом Вас поддерживаю, обычно это предполагает и отсутствие предмета обсуждения. Но раз уж отлавливаем faultы, то смысл заглянуть в ассемблер есть. А порыться в том, что наделал компилятор я лично люблю, бывает очень полезно и познавательно.
Go to the top of the page
 
+Quote Post
Forger
сообщение Mar 31 2017, 15:04
Сообщение #61


Профессионал
*****

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



Цитата(Шаманъ @ Mar 31 2017, 17:35) *
Но раз уж отлавливаем faultы, то смысл заглянуть в ассемблер есть.

Честно, мне было бы вломы рыться в том, что там наделал компилятор на мою кривую конструкцию.
По мне быстрее и проще переписать саму кривую конструкцию, на которой вылезает fault, иначе этот fault вылезет в другом месте ....
Но если бесконечный поиск fault-ов и ковыряние в ассемблере - это некое хобби, то это меняет дело sm.gif


--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
Go to the top of the page
 
+Quote Post
Шаманъ
сообщение Mar 31 2017, 16:08
Сообщение #62


Знающий
****

Группа: Участник
Сообщений: 758
Регистрация: 27-08-08
Пользователь №: 39 839



Цитата(Forger @ Mar 31 2017, 18:04) *
Честно, мне было бы вломы рыться в том, что там наделал компилятор на мою кривую конструкцию.

У меня конструкции обычно достаточно прямые, чтобы код (в смысле сгенерированный компилятором) легко читался.

Цитата
Но если бесконечный поиск fault-ов и ковыряние в ассемблере - это некое хобби, то это меняет дело sm.gif

Не надо передергивать. За последние пол года могу вспомнить только два случая, оба решились в течении пары минут.
Go to the top of the page
 
+Quote Post
Forger
сообщение Mar 31 2017, 16:28
Сообщение #63


Профессионал
*****

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



Цитата(Шаманъ @ Mar 31 2017, 19:08) *
У меня конструкции обычно достаточно прямые, чтобы код (в смысле сгенерированный компилятором) легко читался.
Не надо передергивать. За последние пол года могу вспомнить только два случая, оба решились в течении пары минут.

Ну, это у вас заняло всего пару минут и, полагаю, что вы можете позволить себе полистать ассемблерный код под хорошую сигару и стаканчик коньяка у теплого камина, так сказать, в удовольствие sm.gif
Однако, я сильно сомневаюсь, что это можно сказать про того, кто готов заводить целые темы только лишь ради поиска тривиальной причины fault-а (я не про ТС конкретно, а воообще, в целом).
Потому и ваша рекомендация "заглянуть в ассемблерный код", по-моему, звучит несколько надменно что ли ...
Впрочем, не лучше звучат и мои персто-указующие назидания wacko.gif

зы. Что-то тема пошла не в то русло ...


--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
Go to the top of the page
 
+Quote Post
Шаманъ
сообщение Mar 31 2017, 17:16
Сообщение #64


Знающий
****

Группа: Участник
Сообщений: 758
Регистрация: 27-08-08
Пользователь №: 39 839



Цитата(Forger @ Mar 31 2017, 19:28) *
Потому и ваша рекомендация "заглянуть в ассемблерный код", по-моему, звучит несколько надменно что ли ...

Та не, я ничего такого не имел ввиду. Извиняюсь, если кого-то обидел. В конце концов все мы когда-то знали и умели мало sm.gif
Go to the top of the page
 
+Quote Post
Forger
сообщение Mar 31 2017, 18:05
Сообщение #65


Профессионал
*****

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



Цитата(Шаманъ @ Mar 31 2017, 20:16) *
В конце концов все мы когда-то знали и умели мало sm.gif

Согласен, очень трудно делиться опытом так, чтобы это не звучало менторским тоном ... у меня ни разу не получалось )))



--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
Go to the top of the page
 
+Quote Post

5 страниц V   1 2 3 > » 
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 20th July 2025 - 13:36
Рейтинг@Mail.ru


Страница сгенерированна за 0.02311 секунд с 7
ELECTRONIX ©2004-2016