MyLibs 1.0
Расширенные библиотеки для STM32
Loading...
Searching...
No Matches
trace.h
Go to the documentation of this file.
1/**
2**************************************************************************
3* @file trace.h
4* @brief Заголочный файл для работы с трассировкой.
5**************************************************************************
6* @addtogroup TRACE Trace defines
7* @ingroup MYLIBS_DEFINES
8* @brief Дефайны для работы с трассировкой
9*************************************************************************/
10#ifndef __TRACE_H_
11#define __TRACE_H_
12#include "mylibs_defs.h"
13
14#include <string.h>
15/**
16 * @addtogroup TRACE_SERIAL Serial trace defines
17 * @ingroup TRACE
18 * @brief Дефайны для работы с serial трассировкой (SWO, RTT)
19 * @details В зависимости от настроек определяется дефайн @ref my_printf() и @ref log_printf() для работы с трассировкой:
20 - @ref SERIAL_TRACE_ENABLE - Если трассировка отключена, то все дефайны определяются как 'ничего'
21 и на производительность кода не влияют
22
23 - @ref RTT_TRACE_ENABLE - для RTT это будет вызов функции SEGGER_RTT_printf()
24
25 Предварительно надо подключить библиотеку SEGGER RTT (SEGGER_RTT.h) и вызвать функцию SEGGER_RTT_Init()
26
27 - @ref SWO_TRACE_ENABLE для SWO это будет просто printf()
28
29 Предварительно надо подключить библиотеку STDOUT и retarget под ITM:
30
31 @verbatim
32 Manage Run-Time Environment -> Compiler -> I/O -> STDOUT -> ITM
33 @endverbatim
34
35 Для SWO также надо включить трассировку:
36
37 @verbatim
38 Options For Target -> Debug -> Debugger Settings
39 @endverbatim
40
41 В вкладке Debug:
42 - Port = SW
43 В вкладке Trace:
44 - Указать Core Clock
45 - Выставить Trace Port = SWO
46 - ITM - выбрать нужный порт (для Keil нулевой порт)
47
48
49 * @{
50 *
51 * @def my_printf(...)
52 * @brief Универсальный макрос для вывода трассировки
53 * @details Варианты реализации:
54 * - RTT_TRACE_ENABLE `SEGGER_RTT_printf(0, ...)`
55 * - SWO_TRACE_ENABLE - `printf(...)`
56 * - NO_TRACE - пустой макрос
57 *
58 * @def log_printf(TAG, fmt, ...)
59 * @brief Макрос логирования с поддержкой уровней @ref LOG_LEVEL
60 * @param TAG Тэг лога
61 * @param fmt, ... Форматируемая строка
62 * @details Варианты реализации:
63 * - @ref LOG_LEVEL == 0 - логирование отключено (макрос пустой)
64 * - @ref LOG_LEVEL == 1 - выводится время @ref local_time и TAG
65 * @code
66 [123] [ADC] Measure Done
67 [456] [ADC] Measure Err
68 * @endcode
69 * - @ref LOG_LEVEL >= 2 - выводится время, TAG, имя файла и номер строки
70 * @code
71 [123] [ADC] (../Core/Src/adc.c:75) Measure Done
72 [456] [ADC] (../Core/Src/adc.c:80) Measure Err
73 * @endcode
74 */
75#ifdef SERIAL_TRACE_ENABLE
76
77 #if defined(RTT_TRACE_ENABLE)
78 #undef SWO_TRACE_ENABLE
79 #include "SEGGER_RTT.h"
80 #define my_printf(...) SEGGER_RTT_printf(0, __VA_ARGS__)
81 #elif defined(SWO_TRACE_ENABLE)
82 #undef RTT_TRACE_ENABLE
83 #define my_printf(...) printf(__VA_ARGS__)
84 #else // NO_TRACE
85 #define my_printf(...)
86 #warning No trace is selected. Serial debug wont work.
87 #endif // RTT_TRACE_ENABLE/SWO_TRACE_ENABLE/NO_TRACE
88#else //SERIAL_TRACE_ENABLE
89
90 #define my_printf(...)
91 #undef RTT_TRACE_ENABLE
92 #undef SWO_TRACE_ENABLE
93
94#endif //SERIAL_TRACE_ENABLE
95
96
97#ifndef local_time
98#define local_time() HAL_GetTick() ///< Локальное время
99#endif
100#ifndef LOG_LEVEL
101#define LOG_LEVEL 1 ///< @brief Уровень логирования (по умолчанию == 1)
102#endif
103
104
105#if LOG_LEVEL == 0 // лог отключен
106 #define \
107log_printf(TAG, fmt, ...)
108#elif LOG_LEVEL == 1 // только тэг
109 #define log_printf(TAG, fmt, ...) \
110my_printf("\n[%lu] [%s] " fmt, \
111(unsigned long)local_time(), TAG, ##__VA_ARGS__)
112#elif LOG_LEVEL >= 2 // всё
113 #define log_printf(TAG, fmt, ...) \
114my_printf("\n[%lu] [%s] (%s:%d) " fmt, \
115(unsigned long)local_time(), TAG, __FILE__, __LINE__, ##__VA_ARGS__)
116#endif
117
118/** TRACE_SERIAL
119 * @}
120 */
121
122/**
123 * @addtogroup TRACE_GPIO GPIO trace defines
124 * @ingroup TRACE
125 * @brief Дефайны для работы с GPIO трассировкой
126 * @details Определяется дефайны для работы с GPIO трассировкой:
127 - TRACE_GPIO_RESET() - для сброса ножки GPIO (через BSRR)
128 - TRACE_GPIO_SET() - для выставления ножки GPIO (через BSRR)
129
130 - Если трассировка @ref GPIO_TRACE_ENABLE отключена, то все дефайны определяются как 'ничего'
131 и на производительность кода не влияют
132 * @{
133 *
134 * @def TRACE_GPIO_RESET(_gpio_, _pin_)
135 * @brief Сбросить указанную ножку GPIO
136 * @param _gpio_ Указатель на структуру GPIO (напр. GPIOA)
137 * @param _pin_ Номер ножки (напр. GPIO_PIN_0)
138 * @details Варианты реализации:
139 * - GPIO_TRACE_ENABLE не определён - макрос пустой
140 * - GPIO_TRACE_ENABLE определён - устанавливает бит сброса через BSRR ((_pin_)<<16)
141 *
142 * @def TRACE_GPIO_SET(_gpio_, _pin_)
143 * @brief Установить указанную ножку GPIO
144 * @param _gpio_ Указатель на структуру GPIO (например GPIOA)
145 * @param _pin_ Номер ножки (напр. GPIO_PIN_0)
146 * @details Варианты реализации:
147 * - GPIO_TRACE_ENABLE не определён - макрос пустой
148 * - GPIO_TRACE_ENABLE определён - устанавливает бит установки через BSRR (_pin_)
149 */
150#ifndef GPIO_TRACE_ENABLE
151 #define TRACE_GPIO_SET(_gpio_,_pin_)
152 #define TRACE_GPIO_RESET(_gpio_,_pin_)
153#else
154 #define TRACE_GPIO_SET(_gpio_,_pin_) (_gpio_)->BSRR = (((_pin_)))
155 #define TRACE_GPIO_RESET(_gpio_,_pin_) (_gpio_)->BSRR = ((_pin_)<<16)
156#endif //GPIO_TRACE_ENABLE
157
158
159/** TRACE_GPIO
160 * @}
161 */
162
163
164
165#if defined(HAL_MODULE_ENABLED) && defined(RTT_TRACE_ENABLE)
166
167/**
168 * @addtogroup TRACE_RTT_FLASH Flash RTT Buffer
169 * @ingroup TRACE
170 * @brief Макросы и функции для сохранения/чтения RTT буфера в Flash
171 * @details Модуль позволяет сохранять данные RTT буфера во Flash и читать их обратно по тегам.
172 * Теги работают следующим образом:
173 * - Базовый тег (младший байт = 0): модуль сам выбирает первый свободный слот во Flash;
174 * новые записи получают автоинкрементированный младший байт тега (от 0x00 до 0xFF).
175 * - Конкретный тег (младший байт != 0): запись или чтение происходит строго с указанным тегом;
176 * если слот с таким тегом уже занят, запись не выполняется.
177 * - Автоинкремент позволяет хранить несколько последовательных записей в пределах одного базового тега,
178 * без необходимости вручную отслеживать адреса Flash или позиции буферов.
179 *
180 * Параметры:
181 * - @ref RTT_FLASH_BUFFER_SIZE - Размер буфера RTT в Flash
182 * - @ref RTT_FLASH_SECTOR - Сектор FLASH куда положится RTT буфер
183 * - @ref RTT_FLASH_SECTOR_START - Начало сектора RTT_FLASH_SECTOR
184 * - @ref RTT_FLASH_SECTOR_END - Конец сектора RTT_FLASH_SECTOR
185 *
186 * @{
187 */
188
189
190/**
191 * @brief Структура RTT, которая будет положена в Flash
192 */
193typedef struct {
194 uint32_t tag; ///< Уникальный идентификатор буфера
195 uint32_t size; ///< Размер данных
196 char data[RTT_FLASH_BUFFER_SIZE]; ///< Буфер RTT
198
199/**
200 * @brief Подготовка Flash к записи
201 * @details Сбрасывает ошибки Flash и ожидает готовности перед записью
202 */
203__STATIC_FORCEINLINE void RTT_FlashPrepare(void)
204{
205 HAL_FLASH_Unlock();
206 __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_PGSERR | FLASH_FLAG_WRPERR | FLASH_FLAG_OPERR);
207 while (__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) {
208 __NOP();
209 }
210}
211
212/**
213 * @brief Сохраняет последние символы RTT-буфера в Flash по тегу
214 * @param tag Базовый или конкретный идентификатор буфера.
215 * @param tail_size Количество последних символов RTT для копирования
216 * @param buf_num Указатель на переменную в которую запишется номер буфера для конкретного тега
217 * @return >=0 — номер буфера (тег) для записи, <0 — ошибка (нет места, тег уже занят, ошибка записи в флеш)
218 *
219 * @details Автоматически копирует последние tail_size символов из RTT-буфера
220 * и записывает их во Flash.
221 * Тег может быть базовым или конкретным:
222 * - Если базовый (младший байт == 0) — будет выбран первый свободный слот с автоинкрементом.
223 * Автоинкремент формируется в пределах от 0x1 до 0xFF
224 * - Если конкретный (младший байт != 0) — запись выполняется только с этим тегом, иначе ошибка.
225 *
226 */
227__STATIC_FORCEINLINE int RTT_SaveToFlash(uint32_t tag, uint32_t tail_size)
228{
229 if (tag == 0xFFFFFFFF)
230 return -1; // Неверный тег
231
232 SEGGER_RTT_BUFFER_UP *up = &_SEGGER_RTT.aUp[0];
233 unsigned buf_size = up->SizeOfBuffer;
234 unsigned wr = up->WrOff;
235
236 // Ограничиваем по размеру буфера RTT и RTT_FLASH_BUFFER_SIZE
237 unsigned n = (tail_size > buf_size) ? buf_size : tail_size;
238 if (n > RTT_FLASH_BUFFER_SIZE)
240
241 uint32_t addr = RTT_FLASH_SECTOR_START;
242 RTT_FlashHeader_t *flash_hdr = NULL;
243 uint32_t base_tag = tag & 0xFFFFFF00;
244 uint32_t next_tag = (tag & 0xFF) == 0 ? tag + 1 : tag;
245
246 // Ищем первый свободный слот, параллельно автоинкрементируем тег
247 while ((addr + sizeof(RTT_FlashHeader_t)) <= RTT_FLASH_SECTOR_END)
248 {
249 flash_hdr = (RTT_FlashHeader_t *)addr;
250
251 if (flash_hdr->tag == 0xFFFFFFFF)
252 break; // Нашли свободное место
253
254
255 if((flash_hdr->tag & 0xFFFFFF00) == base_tag) // выбраный тег
256 {
257 if ((tag & 0xFF) == 0) // если он базовый - ищем последний
258 next_tag = flash_hdr->tag + 1; // автоинкремент
259 else
260 if(flash_hdr->tag == tag) // если он конкретный и уже существует - то ошибка
261 return -1; // конкретный тег уже занят
262 }
263
264
265 if(next_tag - tag > 0xFF)
266 return -1; // автоинкремент слишком большой
267
268 addr += sizeof(RTT_FlashHeader_t);
269 }
270
271 if ((addr + sizeof(RTT_FlashHeader_t)) > RTT_FLASH_SECTOR_END)
272 return -1; // Нет свободного места
273
274 // Копируем последние n символов из RTT
275 char temp[RTT_FLASH_BUFFER_SIZE];
276 unsigned valid_count = 0;
277
278 for (unsigned i = 0; i < n; i++)
279 {
280 unsigned idx = (wr + buf_size - n + i) % buf_size;
281 char c = up->pBuffer[idx];
282 if (c != 0)
283 temp[valid_count++] = c;
284 }
285
287
288 // Формируем структуру в RAM
289 RTT_FlashHeader_t flash_data;
290 flash_data.tag = next_tag;
291 flash_data.size = valid_count;
292 memcpy(flash_data.data, temp, valid_count);
293
294 // Записываем структуру во Flash (по 4 байта)
295 const uint32_t *p = (const uint32_t *)&flash_data;
296 for (unsigned i = 0; i < sizeof(RTT_FlashHeader_t) / 4; i++)
297 {
298 if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, addr + i * 4, p[i]) != HAL_OK)
299 return -1;
300 }
301
302 HAL_FLASH_Lock();
303 __DSB();
304 __ISB();
305
306
307 return (int)(next_tag&0xFF);
308}
309
310
311/**
312 * @brief Читает последние символы RTT-буфера из Flash по тегу
313 * @param tag Базовый или конкретный идентификатор буфера.
314 * @param Buffer Буфер назначения для копирования данных
315 * @param tail_size Количество последних символов, которые нужно прочитать
316 * @param read_size Количество считанных символов
317 * @return >=0 — номер буфера (тег) для записи, <0 — ошибка (тег не найден или структура повреждена)
318 *
319 * @details Копирует последние tail_size символов из найденной записи Flash в Buffer.
320 * Тег может быть базовым или конкретным:
321 * - Если базовый (младший байт == 0) — будет прочитана последняя запись из группы.
322 * - Если конкретный (младший байт != 0) — прочитывается именно эта запись.
323 */
324__STATIC_FORCEINLINE int RTT_ReadFromFlash(uint32_t tag, char *Buffer, uint32_t tail_size, uint32_t *read_size)
325{
326 if (!Buffer || tail_size == 0)
327 return -1; // Неверные параметры
328
329 if (tag == 0xFFFFFFFF)
330 return -1; // Недопустимый тег
331
332 uint32_t addr = RTT_FLASH_SECTOR_START;
333 RTT_FlashHeader_t *flash_hdr = NULL;
334 RTT_FlashHeader_t *target_hdr = NULL;
335 uint32_t base_tag = tag & 0xFFFFFF00;
336
337 // Поиск записи по тегу
338 while ((addr + sizeof(RTT_FlashHeader_t)) <= RTT_FLASH_SECTOR_END)
339 {
340 flash_hdr = (RTT_FlashHeader_t *)addr;
341
342 if (flash_hdr->tag == 0xFFFFFFFF)
343 break; // Достигнут конец записанных структур
344
345 // выбраный тег
346 if((flash_hdr->tag & 0xFFFFFF00) == base_tag)
347 {
348 if ((tag & 0xFF) == 0) // если он базовый - ищем последний
349 target_hdr = flash_hdr; // сохраняем последний в группе
350 else
351 if(flash_hdr->tag == tag) // если он конкретный и найден - берем его
352 {
353 target_hdr = flash_hdr;
354 break; // конкретный тег найден
355 }
356 }
357
358 addr += sizeof(RTT_FlashHeader_t);
359 }
360
361 if (!target_hdr) return -1; // Тег не найден
362
363 // Проверка корректности размера
364 if (target_hdr->size > RTT_FLASH_BUFFER_SIZE)
365 return -1; // Повреждённая запись
366
367 // Определяем количество читаемых символов
368 uint32_t n = (tail_size > target_hdr->size) ? target_hdr->size : tail_size;
369 // Начальная позиция для чтения последних tail_size символов
370 uint32_t start = target_hdr->size - n;
371 // Копируем данные из Flash в RAM
372 memcpy(Buffer, &target_hdr->data[start], n);
373
374 if(read_size != NULL)
375 {
376 *read_size = n;
377 }
378
379 __DSB();
380 __ISB();
381
382 return (int)(target_hdr->tag & 0xFF);
383}
384
385/**
386 * @brief Стирание сектора Flash с RTT-буфером
387 */
388__STATIC_FORCEINLINE int RTT_EraseFlash(void)
389{
390 FLASH_EraseInitTypeDef eraseInit;
391 uint32_t pageError = 0;
392
394
395 eraseInit.TypeErase = FLASH_TYPEERASE_SECTORS;
396 eraseInit.Sector = RTT_FLASH_SECTOR;
397 eraseInit.NbSectors = 1;
398
399 if (HAL_FLASHEx_Erase(&eraseInit, &pageError) != HAL_OK)
400 {
401 return -1;
402 }
403 return 0;
404 HAL_FLASH_Lock();
405}
406
407/** TRACE_RTT_FLASH
408 * @}
409 */
410
411#else // HAL_MODULE_ENABLED && RTT_TRACE_ENABLE
412#define RTT_FlashPrepare(...)
413#define RTT_EraseFlash(...) 0
414#define RTT_SaveToFlash(...) 0
415#define RTT_ReadFromFlash(...) 0
416#endif // HAL_MODULE_ENABLED && RTT_TRACE_ENABLE
417
418
419
420
421/**
422 * @addtogroup TRACE_HARDFAULT Hardfault trace defines
423 * @ingroup TRACE
424 * @brief Модуль трассировки HardFault с возможностью сохранения RTT буфера во Flash
425 * @details
426 * Этот модуль позволяет сохранять контекст процессора и последние символы RTT буфера при возникновении HardFault.
427 *
428 * Механизм работы:
429 * - При срабатывании HardFault вызывается HF_HandleFault(), который:
430 * 1. Получает указатель на стек, где произошёл HardFault (MSP или PSP).
431 * 2. Выводит значения регистров R0-R3, R12, LR, PC, PSR и системных регистров SCB.
432 * 3. Формирует строку с регистрами и копирует последние символы RTT буфера.
433 * 4. Сохраняет данные во Flash с базовым тегом HF_RTT_TAG_BASE.
434 * - Для восстановления последнего HardFault используется HF_CheckRecovered(), который:
435 * 1. Читает запись во Flash по базовому тегу.
436 * 2. Выводит сохранённый RTT буфер и контекст регистров.
437 * 3. Опционально стирает Flash после восстановления.
438 *
439 * Параметры:
440 * - @ref HARDFAULT_SERIAL_TRACE - Включить обработку и serial трассировку Hardfault
441 * Если отключена то вставляются заглушки, никак не влияющие на параметры и остальную программу
442 * - @ref HF_RTT_TAG_BASE - Базовый тег RTT Flash для HardFault
443 * - @ref HF_RTT_TAIL_SIZE - Размер буфера RTT, который сохранится при Hardfault
444 * - @ref HF_STACK_DUMP_WORDS - Сколько слов стека будет проанализировано во время Hardfault
445 * - @ref HF_FLASH_ADDR - Адрес FLASH куда положится RTT буфер
446 * - @ref HF_RAM_END - Конец RAM памяти (чтобы во время анализа стека не выйти за пределы)
447 *
448 @code
449 void Hardfault()
450 {
451 HF_HandleFault();
452 NVIC_SystemReset();
453 }
454
455 int main()
456 {
457 if(HF_CheckRecovered(0))
458 {
459 //set hardfault error
460 RTT_EraseFlash(); // erase rtt flash after message readed
461 }
462 }
463 @endcode
464 * @{
465 */
466#if defined(HAL_MODULE_ENABLED) && defined(HARDFAULT_SERIAL_TRACE)
467
468#ifndef HF_RTT_TAIL_SIZE
469#define HF_RTT_TAIL_SIZE RTT_FLASH_BUFFER_SIZE ///< Размер буфера RTT, который сохранится при Hardfault
470#endif
471
472/**
473 * @brief Контекст стек-фрейма процессора при HardFault
474 * @details Сохраняет регистры R0-R3, R12, LR, PC, PSR для последующего анализа.
475 */
476typedef struct {
477 uint32_t r0; ///< Регистр R0
478 uint32_t r1; ///< Регистр R1
479 uint32_t r2; ///< Регистр R2
480 uint32_t r3; ///< Регистр R3
481 uint32_t r12; ///< Регистр R12
482 uint32_t lr; ///< Link Register
483 uint32_t pc; ///< Program Counter
484 uint32_t psr; ///< Program Status Register
486
487/**
488 * @brief Проверка и вывод последнего HardFault-трейса из Flash
489 * @details
490 * Функция ищет последнюю запись HardFault по базовому тегу HF_RTT_TAG_BASE
491 * и выводит её содержимое в консоль. После успешного вывода Flash можно опционально очистить.
492 *
493 * @return int
494 * - 1 — данные HardFault найдены и выведены
495 * - 0 — данные отсутствуют или тег не найден
496 *
497 * @note Вызов рекомендуется при инициализации приложения для анализа предыдущего сбоя.
498 */
499__STATIC_FORCEINLINE int HF_CheckRecovered(int erase)
500{
501 char buffer[RTT_FLASH_BUFFER_SIZE];
502 uint32_t read_size = 0;
503 int n_hardfault = RTT_ReadFromFlash(HF_RTT_TAG_BASE, buffer, HF_RTT_TAIL_SIZE, &read_size);
504 if (n_hardfault > 0)
505 {
506 my_printf("\n--- Recovered HardFault RTT buffer #%u ---\n", n_hardfault);
507 for (int i = 0; i < read_size; i++)
508 {
509 char c = buffer[i];
510 if (c == 0 || c == (char)0xFF) break;
511 my_printf("%c", c);
512 }
513
514 if(erase)
516 my_printf("\n--------- HardFault Dump End ---------\n");
517 return 1;
518 }
519 return 0;
520}
521
522
523static HF_StackFrame_t *stack_frame;
524static uint32_t stack_dump[HF_STACK_DUMP_WORDS];
525static void *ret_adr[10] = {0};
526/**
527 * @brief Обработчик HardFault
528 * @details
529 * Вызывается из прерывания HardFault или в любом месте где понятно что ошибка критическая.
530 * Последовательно выполняет:
531 * 1. Определяет активный стек (MSP или PSP) на момент сбоя.
532 * 2. Сохраняет значения регистров R0-R3, R12, LR, PC, PSR.
533 * 3. Выводит системные регистры CFSR, HFSR, DFSR, AFSR, MMFAR, BFAR.
534 * 4. Формирует stack trace с 3 уровнями возврата.
535 * 5. Копирует последние символы RTT буфера.
536 * 6. Сохраняет все данные во Flash через RTT_SaveToFlash с базовым тегом HF_RTT_TAG_BASE.
537 *
538 * @note Функция защищена, так как вызывается в контексте сбоя — минимизирует использование вызовов HAL.
539 */
540__STATIC_FORCEINLINE void HF_HandleFault(void)
541{
542 // Получаем указатель на стек, где произошёл HardFault
543 __ASM volatile(
544 "TST lr, #4 \n"
545 "ITE EQ \n"
546 "MRSEQ %[ptr], MSP\n"
547 "MRSNE %[ptr], PSP\n"
548 : [ptr] "=r"(stack_frame)
549 );
550
551 my_printf("\n===== HardFault occurred! =====\n");
552 my_printf("R0 = 0x%08X\n", stack_frame->r0);
553 my_printf("R1 = 0x%08X\n", stack_frame->r1);
554 my_printf("R2 = 0x%08X\n", stack_frame->r2);
555 my_printf("R3 = 0x%08X\n", stack_frame->r3);
556 my_printf("R12 = 0x%08X\n", stack_frame->r12);
557 my_printf("LR = 0x%08X\n", stack_frame->lr);
558 my_printf("PC = 0x%08X\n", stack_frame->pc);
559 my_printf("PSR = 0x%08X\n", stack_frame->psr);
560
561 my_printf("CFSR = 0x%08X\n", SCB->CFSR);
562 my_printf("HFSR = 0x%08X\n", SCB->HFSR);
563 my_printf("DFSR = 0x%08X\n", SCB->DFSR);
564 my_printf("AFSR = 0x%08X\n", SCB->AFSR);
565 my_printf("MMFAR = 0x%08X\n", SCB->MMFAR);
566 my_printf("BFAR = 0x%08X\n", SCB->BFAR);
567
568 // --- Stack trace ---
569 my_printf("--- Stack trace ---\n");
570 ret_adr[0] = __builtin_return_address(0);
571 ret_adr[1] = __builtin_return_address(1);
572 ret_adr[2] = __builtin_return_address(2);
573
574 for (int i = 0; i < 3; i++) // развернуть n уровней
575 {
576 if(ret_adr[i])
577 my_printf(" #%d: 0x%08lX\r\n", i, ret_adr[i]); // -1 для Thumb
578 }
580}
581#else // HAL_MODULE_ENABLED && HARDFAULT_SERIAL_TRACE
582#define HF_CheckRecovered(...) 0
583#define HF_HandleFault(...)
584#endif // HAL_MODULE_ENABLED && HARDFAULT_SERIAL_TRACE
585/** TRACE_HARDFAULT
586 * @}
587 */
588
589
590
591#endif //__TRACE_H_
#define RTT_FLASH_SECTOR
Сектор FLASH куда положится RTT буфер
#define RTT_FLASH_BUFFER_SIZE
Размер буфера RTT в Flash.
#define RTT_FLASH_SECTOR_START
Начало сектора RTT_FLASH_SECTOR.
#define HF_STACK_DUMP_WORDS
Сколько слов стека будет проанализировано во время Hardfault.
#define HF_RTT_TAG_BASE
базовый тег для HardFault
#define HF_RTT_TAIL_SIZE
Размер буфера RTT, который сохранится при Hardfault.
#define RTT_FLASH_SECTOR_END
Конец сектора RTT_FLASH_SECTOR.
__STATIC_FORCEINLINE int HF_CheckRecovered(int erase)
Проверка и вывод последнего HardFault-трейса из Flash.
Definition trace.h:499
__STATIC_FORCEINLINE void HF_HandleFault(void)
Обработчик HardFault.
Definition trace.h:540
__STATIC_FORCEINLINE void RTT_FlashPrepare(void)
Подготовка Flash к записи
Definition trace.h:203
__STATIC_FORCEINLINE int RTT_ReadFromFlash(uint32_t tag, char *Buffer, uint32_t tail_size, uint32_t *read_size)
Читает последние символы RTT-буфера из Flash по тегу
Definition trace.h:324
__STATIC_FORCEINLINE int RTT_SaveToFlash(uint32_t tag, uint32_t tail_size)
Сохраняет последние символы RTT-буфера в Flash по тегу
Definition trace.h:227
__STATIC_FORCEINLINE int RTT_EraseFlash(void)
Стирание сектора Flash с RTT-буфером
Definition trace.h:388
#define my_printf(...)
Универсальный макрос для вывода трассировки
Definition trace.h:80
Заголочный файл для дефайнов библиотеки MyLibsGeneral.
Контекст стек-фрейма процессора при HardFault.
Definition trace.h:476
uint32_t pc
Program Counter.
Definition trace.h:483
uint32_t r1
Регистр R1.
Definition trace.h:478
uint32_t r0
Регистр R0.
Definition trace.h:477
uint32_t r3
Регистр R3.
Definition trace.h:480
uint32_t r2
Регистр R2.
Definition trace.h:479
uint32_t lr
Link Register.
Definition trace.h:482
uint32_t r12
Регистр R12.
Definition trace.h:481
uint32_t psr
Program Status Register.
Definition trace.h:484
Структура RTT, которая будет положена в Flash.
Definition trace.h:193
uint32_t tag
Уникальный идентификатор буфера
Definition trace.h:194
char data[1024]
Буфер RTT.
Definition trace.h:196
uint32_t size
Размер данных
Definition trace.h:195