Перейти к содержанию
    

Исключение Hard Fault на Cortex-M3

смотреть в сторону DWT

Data Watchpoint and Trace

при старте OpenOCD строка наподобие следующей есть?:
    Info : cpu: hardware has 6 breakpoints, 4 watchpoints

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 8/13/2024 at 3:01 PM, kpv said:

смотреть в сторону DWT

Data Watchpoint and Trace

при старте OpenOCD строка наподобие следующей есть?:
    Info : cpu: hardware has 6 breakpoints, 4 watchpoints

При запуске сервера:

koluna@lev:~$ openocd -f interface/jlink.cfg -c "transport select swd" -f target/stm32f1x.cfg
Open On-Chip Debugger 0.12.0-rc1
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
swd
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : J-Link ARM V8 compiled Nov 14 2012 22:34:52
Info : Hardware version: 8.00
Info : VTarget = 3.313 V
Info : clock speed 1000 kHz
Info : SWD DPIDR 0x1ba01477
Info : [stm32f1x.cpu] Cortex-M3 r1p1 processor detected
Info : [stm32f1x.cpu] target has 6 breakpoints, 4 watchpoints
Info : starting gdb server for stm32f1x.cpu on 3333
Info : Listening on port 3333 for gdb connections

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

50 minutes ago, koluna said:
koluna@lev:~$ openocd -f interface/jlink.cfg -c "transport select swd" -f target/stm32f1x.cfg

Если вы так в консоли и работаете, то вам сюда: https://openocd.org/doc/html/General-Commands.html раздел "15.5 Breakpoint and Watchpoint commands". Но вроде б сейчас все IDE оборудованы соответствующими кнопками?..

 

Но, по сути, причину ошибки вам уже подсказали - переполнение приёмного буфера.
Простейшее (и необходимое!) решение - условие (принято == длина_пакета) меняем на (принято >= длина пакета).
И, кстати, банальный вопрос: поле "длина пакета" в заголовке - это длина данных или длина всего пакета вместе с заголовком?


Также, как верно заметил jcxz, при таймаутах весь приём напрочь ломается. Если в линии по какой-то причине пропал один байт, вы попадёте в условие проверки таймаута по заголовку следующего пакета, и сразу же пропускаете первый байт заголовка. Хорошо ещё, если пропустите пакет целиком, а не найдёте магические два байта в середине данных...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 часа назад, koluna сказал:

Делал так, не выходит из исключения и ведет себя как-то странно... как бы подвисает чтоли...

Смотрите содержимое указателя стека и ячеек по адресам, куда указывает указатель - есть ли там адрес точки возврата в нужном месте? И если нет - куда он делся, ведь только что должен был сохраниться при входе в исключение.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 8/13/2024 at 4:15 PM, esaulenka said:

Но вроде б сейчас все IDE оборудованы соответствующими кнопками?..

Code::Blocks у меня. Я не разбирался как к нему отладчик прикручивать. Крайне редко им пользуюсь, обходилось всегда.

 

On 8/13/2024 at 4:15 PM, esaulenka said:

Простейшее (и необходимое!) решение - условие (принято == длина_пакета) меняем на (принято >= длина пакета).

Да, я пробовал. Не помогает...

On 8/13/2024 at 4:15 PM, esaulenka said:

И, кстати, банальный вопрос: поле "длина пакета" в заголовке - это длина данных или длина всего пакета вместе с заголовком?

Длина всего пакета полностью.

On 8/13/2024 at 4:15 PM, esaulenka said:

Также, как верно заметил jcxz, при таймаутах весь приём напрочь ломается. Если в линии по какой-то причине пропал один байт, вы попадёте в условие проверки таймаута по заголовку следующего пакета, и сразу же пропускаете первый байт заголовка. Хорошо ещё, если пропустите пакет целиком, а не найдёте магические два байта в середине данных...

Да, спасибо, поправлю. Но если бы был таймаут, то мой программный дебаг сообщил бы об этом...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 minute ago, EdgeAligned said:

В момент ошибки значение регистра BFAR - какое?

Так он говорил уже - сразу за концом памяти. 99% вероятности, что это переполнение массива.

 

9 minutes ago, koluna said:

Да, я пробовал. Не помогает...

Я внимательно посмотрел на ваш отладчик

(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

давайте читать с конца:

- exchange.c, 175 - это какая строчка в приведённом вами waitForRequest() ?

- dbgout() как устроен? С exchXXXX() никак не связан (другой уарт, полностью независимый набор флажков и т.д.) ?

- exchTXEHandler() что из себя представляет? Что у него в переменных в момент хардфолта?

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А теперь смотрим инструкицю, вызвавшую это переполнение. Её адрес - указывается в PC, как написано в мануале. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 8/13/2024 at 5:07 PM, esaulenka said:

- exchange.c, 175 - это какая строчка в приведённом вами waitForRequest() ?

Строка:

dbgout(LOG_DEBUG, "[%s()] Wait for packet... ", __func__);

Код поменял, сейчас немного по-другому, но тоже самое:

(gdb) backtrace 
#0  HardFault_Handler () at ./src/main.c:139
#1  <signal handler called>
#2  0x0800165e in exchTXEHandler () at ./src/libs/exchange/exchange.c:361
#3  <signal handler called>
#4  dbgout (level=level@entry=7, format=0x80017cb <EXCH_process+278> "H\377\367\222\370\276#+\200\245\347PN") at ./src/libs/dbg/dbg.c:19
#5  0x080017ca in waitForRequest (exchRes=0x20000f00 <exchRes.7248>, pt=0x20000f0c <ptChild.7247>) at ./src/libs/exchange/exchange.c:187
#6  EXCH_process (pt=0x20001fec) at ./src/libs/exchange/exchange.c:483
#7  0xf4f3f7fc in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)

 

On 8/13/2024 at 5:07 PM, esaulenka said:

- dbgout() как устроен? С exchXXXX() никак не связан (другой уарт, полностью независимый набор флажков и т.д.) ?

void dbgout(const int32_t level, const char* format, ...)
{
    UNUSED(level);

    va_list args;

    va_start(args, format);
    xvprintf(format, args);
    va_end(args);
}

Используется библиотека xprintf, переопределил для нее функцию вывода байта в USART1.
Интерфейс, на котором сбои - USART2. 
Никак они не связаны.

On 8/13/2024 at 5:07 PM, esaulenka said:

exchTXEHandler() что из себя представляет? Что у него в переменных в момент хардфолта?

По сути - в нем проблема или где-то рядом... 

Передачу запускаю следующей функцией:

static PT_THREAD(sendReply(PT* pt))
{
    PT_BEGIN(pt);

    txCnt = 0;
    txComplete = false;

    exchTxeEnable();                                                            // Запускаем передачу.

    dbgout(LOG_DEBUG, "[%s()] Send packet %u bytes...\n", __func__, txSize);
    static bool tmp;
    do
    {
        PT_YIELD(pt);

        ENTER_CRITICAL();
        tmp = txComplete;
        EXIT_CRITICAL();
    }
    while(!tmp);
    dbgout(LOG_DEBUG, "[%s()] Send packet was completed.\n", __func__);
    txComplete = false;

    dbgout(LOG_DEBUG, "[%s()] Transaction trs: %u\n", __func__, transId);
    transId++;

    PT_END(pt);
}

В txSize размер пакета для передачи. Цикл с ожиданием для эксперимента. Ранее было просто PT_WAIT_UNTIL(pt, txComplete);

Функция, вызываемая из обработчика (сейчас без проверки на переполнение):

void exchTXEHandler(void)
{
    exchWriteByte(exchBuff[txCnt]);
    txCnt++;

    if(txCnt == txSize)
    {
        exchTxeDisable();
        txComplete = true;
    }
}

Вывод отладчика:

(gdb) up 2
#2  0x0800165e in exchTXEHandler () at ./src/libs/exchange/exchange.c:361
361	    exchWriteByte(exchBuff[txCnt]);
(gdb) list
356	//    }
357	//}
358	
359	void exchTXEHandler(void)
360	{
361	    exchWriteByte(exchBuff[txCnt]);
362	    txCnt++;
363	
364	    if(txCnt == txSize)
365	    {
(gdb) frame
#2  0x0800165e in exchTXEHandler () at ./src/libs/exchange/exchange.c:361
361	    exchWriteByte(exchBuff[txCnt]);
(gdb) info frame
Stack level 2, frame at 0x20001f8c:
 pc = 0x800165e in exchTXEHandler (./src/libs/exchange/exchange.c:361); saved pc = 0xfffffff9
 called by frame at 0x20001fac, caller of frame at 0x20001f7c
 source language c.
 Arglist at 0x20001f7c, args: 
 Locals at 0x20001f7c, Previous frame's sp is 0x20001f8c
 Saved registers:
  r4 at 0x20001f7c, r5 at 0x20001f80, r6 at 0x20001f84, lr at 0x20001f88

 

On 8/13/2024 at 4:59 PM, EdgeAligned said:

В момент ошибки значение регистра BFAR - какое?

Да, биты BFARVALID и PRECIS ERR установлены.

Да, BFAR содержит корректный адрес: этот адрес 20002000 - RAM.
Видимо, что-то оттуда попыталось прочитаться или записаться.
Я выводил своим дебагом, там много кода... значение будет некорректным, наверное.
Только в отладчике смотреть?

 

Поставил брекпойнт на HardFault_Handler(). Вот информация при остановке:

Breakpoint 1, HardFault_Handler () at ./src/main.c:126
126		dbgout(LOG_DEBUG, "\n[%s()] !!! System fault !!!\n", __func__);
(gdb) list
121	//    LR_read = *((uint32_t*) ((uint32_t) MSP_read + 5 * 4));
122	//    PC_read = *((uint32_t*) ((uint32_t) MSP_read + 6 * 4));
123	
124	
125	
126		dbgout(LOG_DEBUG, "\n[%s()] !!! System fault !!!\n", __func__);
127		dbgout(LOG_DEBUG, "[%s()] HFSR=x%08X\n", __func__, SCB->HFSR);
128		dbgout(LOG_DEBUG, "[%s()] CFSR=x%08X\n", __func__, SCB->CFSR);
129		dbgout(LOG_DEBUG, "[%s()] BFAR=x%08X\n", __func__, SCB->BFAR);
130	
(gdb) info frame
Stack level 0, frame at 0x20001f5c:
 pc = 0x8000354 in HardFault_Handler (./src/main.c:126); saved pc = 0xfffffff1
 called by frame at 0x20001f7c
 source language c.
 Arglist at 0x20001f5c, args: 
 Locals at 0x20001f5c, Previous frame's sp is 0x20001f5c

pc = 0x8000354 - по этому адресу сбойная инструкция?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Как я понял, строка 0354 4FEA5000         lsr    r0, r0, #1?

 110:./src/libs/exchange/exchange.c ****             if (temp == 0)
 1563              		.loc 1 110 36 is_stmt 0 view .LVU502
 1564 0340 80EA0201 		eor	r1, r0, r2
 111:./src/libs/exchange/exchange.c ****             {
 1565              		.loc 1 111 16 view .LVU503
 1566 0344 C907     		lsls	r1, r1, #31
 1567 0346 03F1FF33 		add	r3, r3, #-1
 1568              	.LVL87:
 119:./src/libs/exchange/exchange.c ****             }
 1569              		.loc 1 119 22 view .LVU504
 1570 034a 48BF     		it	mi
 1571 034c 80F48C70 		eormi	r0, r0, #280
 1572              	.LVL88:
 119:./src/libs/exchange/exchange.c ****             }
 1573              		.loc 1 119 22 view .LVU505
 1574              	.LBE126:
 108:./src/libs/exchange/exchange.c ****         {
 1575              		.loc 1 108 9 view .LVU506
 1576 0350 13F0FF03 		ands	r3, r3, #255
 1577              	.LBB127:
 119:./src/libs/exchange/exchange.c ****             }
 1578              		.loc 1 119 22 view .LVU507
 1579 0354 4FEA5000 		lsr	r0, r0, #1
 1580              	.LVL89:
 121:./src/libs/exchange/exchange.c ****         }
 1581              		.loc 1 121 13 is_stmt 1 view .LVU508
 121:./src/libs/exchange/exchange.c ****         }
 1582              		.loc 1 121 18 is_stmt 0 view .LVU509
 1583 0358 4FEA5202 		lsr	r2, r2, #1
 1584              	.LVL90:
 121:./src/libs/exchange/exchange.c ****         }
 1585              		.loc 1 121 18 view .LVU510
 1586              	.LBE127:
 108:./src/libs/exchange/exchange.c ****         {
 1587              		.loc 1 108 49 is_stmt 1 view .LVU511
 108:./src/libs/exchange/exchange.c ****         {
 1588              		.loc 1 108 35 view .LVU512
 108:./src/libs/exchange/exchange.c ****         {
 1589              		.loc 1 108 9 is_stmt 0 view .LVU513

 

Как объяснить ситуацию, когда после перепрошивки МК Hard Fault всегда возникает сразу?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

21 minutes ago, koluna said:

Только в отладчике смотреть?

То, что тут написано по вытаскиванию информации из стэка и регистров, отладчик вытаскивает автоматом и чуть ли не в физию тебе тычет адресом сбойной команды и её операндами, причём прям в программе и дизасме встаёт на строки со сбойной командой. После такого причина ошибки в большинстве случаев очевидна, или понятно, куда рыть. Так сейчас работает gdb в Кубе.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

6 минут назад, koluna сказал:

когда после перепрошивки МК Hard Fault всегда возникает сразу?

Ура, теперь вы сломали код так, что он сбоит всегда, а не время от времени 🙂 Это уже прогресс. Теперь осталось вспомнить, что изменили в коде, что привело к такому результату?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 8/13/2024 at 5:58 PM, EdgeAligned said:

Ура, теперь вы сломали код так, что он сбоит всегда, а не время от времени 🙂 Это уже прогресс. Теперь осталось вспомнить, что изменили в коде, что привело к такому результату?

Оно давно так уже... наверное, изначально даже... просто не сразу заметил и сообщил об этом...

On 8/13/2024 at 5:56 PM, tonyk_av said:

То, что тут написано по вытаскиванию информации из стэка и регистров, отладчик вытаскивает автоматом и чуть ли не в физию тебе тычет адресом сбойной команды и её операндами, причём прям в программе и дизасме встаёт на строки со сбойной командой. После такого причина ошибки в большинстве случаев очевидна, или понятно, куда рыть. Так сейчас работает gdb в Кубе.

Все бы ничего, наверное, но я через CLI отлаживаю и у меня пару вопросов:

(gdb) backtrace 
#0  HardFault_Handler () at ./src/main.c:139
#1  <signal handler called>
#2  0x0800165e in exchTXEHandler () at ./src/libs/exchange/exchange.c:361
#3  <signal handler called>
#4  dbgout (level=level@entry=7, format=0x80017cb <EXCH_process+278> "H\377\367\222\370\276#+\200\245\347PN") at ./src/libs/dbg/dbg.c:19
#5  0x080017ca in waitForRequest (exchRes=0x20000f00 <exchRes.7248>, pt=0x20000f0c <ptChild.7247>) at ./src/libs/exchange/exchange.c:187
#6  EXCH_process (pt=0x20001fec) at ./src/libs/exchange/exchange.c:483
#7  0xf4f3f7fc in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)

Что значат строки <signal handler called>.
Видимо, строка Backtrace stopped: previous frame identical to this frame (corrupt stack?) говорит о том, что что-то пошло не так?
Ранее, когда пользовался отладчиком, мне хватало информации, чтобы быстро найти ошибку. А сейчас слишком много нового и непонятного...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

25 минут назад, koluna сказал:

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

Вроде бы вся информация и ответы "где баг" вам уже дана. Неужто до сих пор не исправили??

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...