Добавлены HardReset в модули Overflow и Assert

This commit is contained in:
cfif 2026-09-29 11:29:40 +03:00
parent f65702e5da
commit 28d9fb8a36
7 changed files with 85 additions and 35 deletions

View File

@ -161,7 +161,19 @@ header file. */
/* USER CODE BEGIN 1 */ /* USER CODE BEGIN 1 */
//#define configASSERT(x) if ((x) == 0) {nvic_system_reset();} //#define configASSERT(x) if ((x) == 0) {nvic_system_reset();}
#define configASSERT(x) if ((x) == 0) {taskDISABLE_INTERRUPTS(); for( ;; );} //#define configASSERT(x) if ((x) == 0) {taskDISABLE_INTERRUPTS(); for( ;; );}
#include "HardFault.h"
#define configASSERT(x) \
if ((x) == 0) { \
taskDISABLE_INTERRUPTS(); \
uint32_t sp; \
__asm volatile ("MRS %0, MSP" : "=r"(sp)); \
HardReset_C_Handler((uint32_t *)sp, 0, HARD_RESET_FREERTOS_ASSERT); \
for( ;; ); /* на случай, если NVIC_SystemReset отключён для отладки */ \
}
/* USER CODE END 1 */ /* USER CODE END 1 */
/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS /* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS

View File

@ -6,6 +6,7 @@
#include "MainModesArbiter.h" #include "MainModesArbiter.h"
#include "LoggerInterface.h" #include "LoggerInterface.h"
#include "PeripheralInterfaces.h" #include "PeripheralInterfaces.h"
#include "HardFault.h"
//#define BOOT_AREA_LENGTH (256 * 1024) //#define BOOT_AREA_LENGTH (256 * 1024)
//#define FIRMWARE_MAIN_ADDR (0x01000000 + BOOT_AREA_LENGTH) //#define FIRMWARE_MAIN_ADDR (0x01000000 + BOOT_AREA_LENGTH)
@ -60,7 +61,17 @@ _Noreturn void stop() {
#if (configCHECK_FOR_STACK_OVERFLOW > 0) #if (configCHECK_FOR_STACK_OVERFLOW > 0)
__attribute__((noreturn)) static void trigger_overflow_reset(void) {
uint32_t sp;
__asm volatile ("MRS %0, MSP" : "=r"(sp));
HardReset_C_Handler((uint32_t *)sp, 0 /* MSP */, HARD_RESET_STACK_OVERFLOW);
__builtin_unreachable();
}
void vApplicationStackOverflowHook(TaskHandle_t xTask, const char *pcTaskName) { void vApplicationStackOverflowHook(TaskHandle_t xTask, const char *pcTaskName) {
trigger_overflow_reset();
PROCESS_UNUSED_VAR(xTask); PROCESS_UNUSED_VAR(xTask);
PROCESS_UNUSED_VAR(pcTaskName); PROCESS_UNUSED_VAR(pcTaskName);
STOP STOP

View File

@ -23,7 +23,21 @@
#ifdef NDEBUG #ifdef NDEBUG
#define DEV_ASSERT(x) ((void)0) #define DEV_ASSERT(x) ((void)0)
#else #else
#define DEV_ASSERT(x) do{}while((x) != 1) // #define DEV_ASSERT(x) do{}while((x) != 1)
#include "FreeRTOS.h"
#include "task.h"
#include "HardFault.h"
#define DEV_ASSERT(x) \
do { \
if ((x) != 1) { \
taskDISABLE_INTERRUPTS(); \
uint32_t sp; \
__asm volatile ("MRS %0, MSP" : "=r"(sp)); \
HardReset_C_Handler((uint32_t *)sp, 0, HARD_RESET_API_ASSERT);\
for( ;; ); \
} \
} while (0)
#endif #endif
#ifndef __IO #ifndef __IO

View File

@ -106,13 +106,13 @@ static void Mma_InitSubSystems(tMma *env) {
firmwareMetaMap_Main->internal_SW_Version.MDB.revision); firmwareMetaMap_Main->internal_SW_Version.MDB.revision);
if (hardFault_magic == 0xDEADBEEF) { if (hardReset_magic == 0xDEADBEEF) {
hardFault_magic = 0; hardReset_magic = 0;
LoggerFormatError(LOGGER, LOG_INFO_TASK_MAIN, "HardFault addresses (%d):", hardFault_count); LoggerFormatError(LOGGER, LOG_INFO_TASK_MAIN, "HardReset %d (%d):", hardReset_type, hardReset_count);
for (uint32 i = 0; i < hardFault_count; ++i) { for (uint32 i = 0; i < hardReset_count; ++i) {
LoggerFormatError(LOGGER, LOG_INFO_TASK_MAIN, " [%d] 0x%08X", i, hardFault_addresses[i]); LoggerFormatError(LOGGER, LOG_INFO_TASK_MAIN, " [%d] 0x%08X", i, hardReset_addresses[i]);
} }
} }

View File

@ -13,18 +13,19 @@ extern uint32_t __StackTop;
#define CODE_START (0x01000000 + 64 * 1024) #define CODE_START (0x01000000 + 64 * 1024)
#define CODE_END (CODE_START + 704 * 1024) // или используйте символ из линкера #define CODE_END (CODE_START + 704 * 1024) // или используйте символ из линкера
__attribute__((section(".save_data"))) volatile uint32_t hardFault_addresses[SIZE_BUF_HARD_FAULT]; // массив для адресов возврата (достаточно 32) __attribute__((section(".save_data"))) volatile uint32_t hardReset_addresses[SIZE_BUF_HARD_FAULT]; // массив для адресов возврата (достаточно 32)
__attribute__((section(".save_data"))) volatile uint32_t hardFault_count; __attribute__((section(".save_data"))) volatile uint32_t hardReset_count;
__attribute__((section(".save_data"))) volatile uint32_t hardFault_magic; __attribute__((section(".save_data"))) volatile uint32_t hardReset_type;
__attribute__((section(".save_data"))) volatile uint32_t hardReset_magic;
__attribute__((section(".save_data"))) volatile uint32_t none_data; __attribute__((section(".save_data"))) volatile uint32_t none_data;
void vTaskGetCurrentTaskStackInfo(void **ppvStackStart, void **ppvStackEnd); void vTaskGetCurrentTaskStackInfo(void **ppvStackStart, void **ppvStackEnd);
void HardFault_C_Handler(uint32_t *sp, uint32_t stack_flag) { void HardReset_C_Handler(uint32_t *sp, uint32_t stack_flag, eHardResetType typeReset) {
uint32_t *src = sp; uint32_t *src = sp;
const uint32_t max_ret = sizeof(hardFault_addresses) / sizeof(uint32_t) - 1; const uint32_t max_ret = sizeof(hardReset_addresses) / sizeof(uint32_t) - 1;
uint32_t *stack_end = NULL; uint32_t *stack_end = NULL;
if (stack_flag == 0) { // Использовался MSP – стек ядра if (stack_flag == 0) { // Использовался MSP – стек ядра
@ -37,19 +38,20 @@ void HardFault_C_Handler(uint32_t *sp, uint32_t stack_flag) {
stack_end = (uint32_t *) pvStackEnd; stack_end = (uint32_t *) pvStackEnd;
} }
hardFault_count = 0; hardReset_count = 0;
while (src < stack_end && hardFault_count < max_ret) { while (src < stack_end && hardReset_count < max_ret) {
uint32_t val = *src; uint32_t val = *src;
// Проверяем, принадлежит ли значение области кода // Проверяем, принадлежит ли значение области кода
if (val >= CODE_START && val < CODE_END) { if (val >= CODE_START && val < CODE_END) {
hardFault_addresses[hardFault_count++] = val & ~1; // убираем Thumb-бит hardReset_addresses[hardReset_count++] = val & ~1; // убираем Thumb-бит
} }
src++; src++;
} }
hardFault_magic = 0xDEADBEEF; hardReset_type = typeReset;
hardReset_magic = 0xDEADBEEF;
NVIC_SystemReset(); NVIC_SystemReset();
} }

View File

@ -7,10 +7,20 @@
#include "stdint.h" #include "stdint.h"
typedef enum {
HARD_RESET_HARD_FAULT = 0x1,
HARD_RESET_STACK_OVERFLOW = 0x2,
HARD_RESET_FREERTOS_ASSERT = 0x3,
HARD_RESET_API_ASSERT = 0x4
} eHardResetType;
extern void HardReset_C_Handler(uint32_t *sp, uint32_t stack_flag, eHardResetType typeReset);
#define SIZE_BUF_HARD_FAULT 32 #define SIZE_BUF_HARD_FAULT 32
extern __attribute__((section(".save_data"))) volatile uint32_t hardFault_addresses[32]; extern __attribute__((section(".save_data"))) volatile uint32_t hardReset_addresses[32];
extern __attribute__((section(".save_data"))) volatile uint32_t hardFault_count; extern __attribute__((section(".save_data"))) volatile uint32_t hardReset_count;
extern __attribute__((section(".save_data"))) volatile uint32_t hardFault_magic; extern __attribute__((section(".save_data"))) volatile uint32_t hardReset_type;
extern __attribute__((section(".save_data"))) volatile uint32_t hardReset_magic;
#endif //HVAC_M7_HARDFAULT_H #endif //HVAC_M7_HARDFAULT_H

View File

@ -1,21 +1,22 @@
.syntax unified .syntax unified
.thumb .thumb
.section .text .section .text
.global HardFault_Handler
.type HardFault_Handler, %function
/* ======================= HARD FAULT ======================= */
.global HardFault_Handler
.type HardFault_Handler, %function
HardFault_Handler: HardFault_Handler:
// Проверяем бит 2 в LR: если 1, то использовался PSP, иначе MSP
TST LR, #4 TST LR, #4
BNE UsePSP BNE Fault_UsePSP
UseMSP: Fault_UseMSP:
MRS R0, MSP // R0 = указатель MSP MRS R0, MSP
MOVS R1, #0 // R1 = флаг 0 (MSP) MOVS R1, #0
B CallHandler B Fault_CallHandler
UsePSP: Fault_UsePSP:
MRS R0, PSP // R0 = указатель PSP MRS R0, PSP
MOVS R1, #1 // R1 = флаг 1 (PSP) MOVS R1, #1
CallHandler: Fault_CallHandler:
LDR R2, =HardFault_C_Handler MOVS R2, #1 // HARD_RESET_HARD_FAULT
BX R2 LDR R3, =HardReset_C_Handler
.size HardFault_Handler, . - HardFault_Handler BX R3
.size HardFault_Handler, . - HardFault_Handler