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