From c12a162450acbeb3ac2ddaad6d69e34a3244f07a Mon Sep 17 00:00:00 2001 From: oganigl Date: Thu, 11 Dec 2025 16:09:26 +0100 Subject: [PATCH 01/18] finished implementation hardfault_handler --- .vscode/settings.json | 3 +- Core/Inc/main.h | 1 - Core/Src/Runes/Runes.cpp | 11 ++ Core/Src/Runes/generated_metadata.cpp | 6 +- Core/Src/main.cpp | 10 +- Core/Src/stm32h7xx_it.c | 171 +++++++++++++++++++++++--- STM32H723ZGTX_FLASH.ld | 8 ++ 7 files changed, 181 insertions(+), 29 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 019c2c08..0126b4a8 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -24,5 +24,6 @@ "mutex": "cpp", "shared_mutex": "cpp", "regex": "cpp" - } + }, + "cortex-debug.variableUseNaturalFormat": true } diff --git a/Core/Inc/main.h b/Core/Inc/main.h index e8512dba..0a0d29d8 100644 --- a/Core/Inc/main.h +++ b/Core/Inc/main.h @@ -146,7 +146,6 @@ void Error_Handler(void); /* USER CODE BEGIN Private defines */ /* USER CODE END Private defines */ - #ifdef __cplusplus } #endif diff --git a/Core/Src/Runes/Runes.cpp b/Core/Src/Runes/Runes.cpp index 511a2cba..254b5a02 100644 --- a/Core/Src/Runes/Runes.cpp +++ b/Core/Src/Runes/Runes.cpp @@ -314,3 +314,14 @@ MultiplierAccelerator::FMACInstance MultiplierAccelerator::Instance = { .dma_write = DMA::Stream::DMA2Stream2, }; #endif + +/************************************************ + * HARD_FAULT + ***********************************************/ +extern "C"{ +GPIO_TypeDef* ports_hard_fault[] = {GPIOB,GPIOB,GPIOE}; +uint16_t pins_hard_fault[] = {GPIO_PIN_0,GPIO_PIN_14,GPIO_PIN_1}; +// //don't touch the count +uint8_t hard_fault_leds_count = (sizeof(ports_hard_fault)/sizeof(GPIO_TypeDef*) == sizeof(pins_hard_fault)/sizeof(uint16_t)) + ? sizeof(pins_hard_fault)/sizeof(uint16_t) : 0; +} \ No newline at end of file diff --git a/Core/Src/Runes/generated_metadata.cpp b/Core/Src/Runes/generated_metadata.cpp index 77dbc457..ed1c47f7 100644 --- a/Core/Src/Runes/generated_metadata.cpp +++ b/Core/Src/Runes/generated_metadata.cpp @@ -5,11 +5,11 @@ extern "C"{ const char DESCRIPTION[255] __attribute__((section(".metadata_pool")))= "****************" // placeholder for beggining - "20250605T165128" // DateTime using ISO-8601 format + "20251211T160625" // DateTime using ISO-8601 format " " // alignment - "77b804dd" // STLIB commit + "dbe4a57f" // STLIB commit "--------" // ADJ commit - "3a365135" // Board commit + "ab5f34fc" // Board commit // the '=' is used for unparsing ; } \ No newline at end of file diff --git a/Core/Src/main.cpp b/Core/Src/main.cpp index e52a3e17..66bc7008 100644 --- a/Core/Src/main.cpp +++ b/Core/Src/main.cpp @@ -1,17 +1,13 @@ #include "main.h" #include "ST-LIB.hpp" - int main(void) { #ifdef SIM_ON SharedMemory::start(); #endif - - DigitalOutput led_on(PB0); + Hard_fault_check(); + volatile uint32_t *bad = (uint32_t*)0xFFFFFFFF; + [[maybe_unused]]uint32_t x = *bad; // dirección ilegal STLIB::start(); - - Time::register_low_precision_alarm(100, [&]() { led_on.toggle(); - }); - while (1) { STLIB::update(); } diff --git a/Core/Src/stm32h7xx_it.c b/Core/Src/stm32h7xx_it.c index 66173658..d54f2ab3 100644 --- a/Core/Src/stm32h7xx_it.c +++ b/Core/Src/stm32h7xx_it.c @@ -20,6 +20,7 @@ /* Includes ------------------------------------------------------------------*/ #include "main.h" #include "stm32h7xx_it.h" +#include "HALAL/Benchmarking_toolkit/HardfaultTrace.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ /* USER CODE END Includes */ @@ -89,33 +90,169 @@ extern FDCAN_HandleTypeDef hfdcan1; /** * @brief This function handles Non maskable interrupt. */ -void NMI_Handler(void) -{ - /* USER CODE BEGIN NonMaskableInt_IRQn 0 */ - /* USER CODE END NonMaskableInt_IRQn 0 */ - /* USER CODE BEGIN NonMaskableInt_IRQn 1 */ - while (1) - { - } - /* USER CODE END NonMaskableInt_IRQn 1 */ + +#define HARDFAULT_HANDLING_ASM(_x) \ + __asm volatile( \ + "tst lr, #4 \n" \ + "ite eq \n" \ + "mrseq r0, msp \n" \ + "mrsne r0, psp \n" \ + "b my_fault_handler_c \n" \ + ) +//calls my_fault_handler with the pointer frame that was being used MSP(Main stack pointer) PSP(process stack pointer) + + //create the space for the hardfault section in the flash +__attribute__((section(".hardfault_log"))) +volatile uint32_t hard_fault[128]; + +static void flash_unlock(void){ + if((FLASH->CR1 & FLASH_CR_LOCK) != 0){ + FLASH->KEYR1 = FLASH_KEY1; + FLASH->KEYR1 = FLASH_KEY2; + } } +static void flash_lock(void){ + FLASH->CR1 |= FLASH_CR_LOCK; +} +static void flash_wait(void){ + while(FLASH->SR1 & FLASH_SR_QW){} +} +static void flash_write_32bytes(uint32_t address,const uint8_t* data){ + if(address & 0X3U){ + return; // the address direction must be aligned 4; + } + flash_wait(); + flash_unlock(); + FLASH->CR1 |= FLASH_CR_PG; //Enable writing + for(volatile size_t i = 0; i < 8; i++){ + *(volatile uint32_t*)(address + i*4) = ((uint32_t*)data)[i]; + } + flash_wait(); + //Disable writing + FLASH->CR1 &= ~FLASH_CR_PG; + flash_lock(); +} +static void flash_write_blockwise(uint32_t address, const uint8_t *data,size_t blocks){ + for(volatile size_t i = 0; i < blocks;i++){ + flash_write_32bytes(address + i*32,data + i*32); + } +} +// //erase hard_fault sector 6 +static void flash_erase_hard_fault_sector(void){ + flash_wait(); + FLASH->CCR1 = 0xFFFFFFFFu; + flash_unlock(); + + FLASH->CR1 |= FLASH_CR_SER | (FLASH_SECTOR_6 << FLASH_CR_SNB_Pos); + //start erase + FLASH->CR1 |= FLASH_CR_START; + flash_wait(); + FLASH->CCR1 = 0xFFFFFFFFU; + // Clean flag + FLASH->CR1 &= ~FLASH_CR_SER; + flash_lock(); +} +//check if we have already write. +static int hardfault_flag_is_set(void){ + return (*(volatile uint32_t *)HF_FLASH_ADDR) == HF_FLAG_VALUE; +} + +#define HALT_IF_DEBUGGING() \ + do { \ + if ((*(volatile uint32_t *)0xE000EDF0) & (1 << 0)) { \ + __asm("bkpt 1"); \ + } \ + } while (0) + //Breakpoint in debug mode + + +volatile uint32_t real_fault_pc; +__attribute__((noreturn,optimize("O0"))) +void my_fault_handler_c(sContextStateFrame *frame) { + // If and only if a debugger is attached, execute a breakpoint + // instruction so we can take a look at what triggered the fault + const uint32_t instr_pc = frame->return_address; + real_fault_pc = instr_pc & ~1; //clean bit 0, real direction + volatile HardFaultLog log_hard_fault; + volatile uint32_t *cfsr = (volatile uint32_t *)0xE000ED28; + //keep the log in the estructure + log_hard_fault.HF_flag = HF_FLAG_VALUE; + log_hard_fault.frame = *frame; + log_hard_fault.CfsrDecode.cfsr = *cfsr; + log_hard_fault.fault_address.Nothing_Valid = 0; + + const uint8_t memory_fault = *cfsr & 0x000000ff; + if(memory_fault){ + const uint8_t MMARVALID = memory_fault & 0b10000000; // We can find the exact place were occured the memory fault + const uint8_t MLSPERR = memory_fault & 0b00100000; // MemManage fault FPU stack + const uint8_t MSTKERR = memory_fault & 0b00010000; // Stack overflow while entring an exception + const uint8_t MUNSTKERR = memory_fault & 0b00001000; // Stack error while exiting from an exception (Corrupted stack) + const uint8_t DACCVIOL = memory_fault & 0b00000010; //Data access violation (acceded to pointer NULL, to a protected memory region, overflow in arrays ...) + const uint8_t IACCVIOL = memory_fault & 0b00000001; //Instruction access violation + if(MMARVALID){ + uint32_t memory_fault_address = *(volatile uint32_t *)0xE000ED34; + log_hard_fault.fault_address.MMAR_VALID = memory_fault_address; + } + HALT_IF_DEBUGGING(); + } + const uint8_t bus_fault = (*cfsr & 0x0000ff00) >> 8; + if(bus_fault){ + const uint8_t BFARVALID = bus_fault & 0b10000000; // BFAR is valid we can know the address which triggered the fault + const uint8_t LSPERR = bus_fault & 0b00100000; //Fault stack FPU + const uint8_t STKERR = bus_fault & 0b00010000; // Fault stack while entring an exception + const uint8_t UNSTKERR = bus_fault & 0b00001000; // Stack error while exiting an exception + const uint8_t IMPRECISERR = bus_fault & 0b00000010; // Bus fault, but the instruction that caused the error can be uncertain + const uint8_t PRECISERR = bus_fault & 0b00000001; //You can read Bfar to find the eact direction of the instruction + if(BFARVALID){ + volatile uint32_t bus_fault_address = *(volatile uint32_t *)0xE000ED38; + log_hard_fault.fault_address.BFAR_VALID = bus_fault_address; + //Don't trust in case IMPRECISERR == 1; + } + HALT_IF_DEBUGGING(); + } + const uint16_t usage_fault = (*cfsr & 0xffff0000) >> 16; + if(usage_fault){ + const uint16_t DIVBYZERO = usage_fault & 0x0200; // Div by ZERO hardfault; + const uint16_t UNALIGNED = usage_fault & 0x0100; // Unaligned access operation occured + const uint16_t NOCP = usage_fault & 0x0008; //Access to FPU when is not present + const uint16_t INVPC = usage_fault & 0x0004; //Invalid program counter load + const uint16_t INVSTATE = usage_fault & 0x0002; // Invalid processor state + const uint16_t UNDEFINSTR = usage_fault & 0x0001; //Undefined instruction. + //HALT_IF_DEBUGGING(); + } + volatile uint8_t metadata_buffer[0x100]; + memcpy(metadata_buffer,(void*)METADATA_FLASH_ADDR,0x100); + flash_erase_hard_fault_sector(); + //write log hard fault + flash_write_blockwise(HF_FLASH_ADDR,(uint8_t*)&log_hard_fault,(sizeof(log_hard_fault) + 31)/32); + //write log Metadata_flash_addr + flash_write_blockwise(METADATA_FLASH_ADDR,metadata_buffer,(0x100)/32); + //reboot the system + volatile uint32_t *aircr = (volatile uint32_t *)0xE000ED0C; + __asm volatile ("dsb"); + *aircr = (0x05FA << 16) | 0x1 << 2; + __asm volatile ("dsb"); + while (1) {} // should be unreachable + } -/** - * @brief This function handles Hard fault interrupt. - */ +__attribute__((naked)) void HardFault_Handler(void) { - /* USER CODE BEGIN HardFault_IRQn 0 */ + HARDFAULT_HANDLING_ASM(); + while (1){} +} - /* USER CODE END HardFault_IRQn 0 */ +void NMI_Handler(void) +{ + /* USER CODE BEGIN NonMaskableInt_IRQn 0 */ + /* USER CODE END NonMaskableInt_IRQn 0 */ + /* USER CODE BEGIN NonMaskableInt_IRQn 1 */ while (1) { - /* USER CODE BEGIN W1_HardFault_IRQn 0 */ - /* USER CODE END W1_HardFault_IRQn 0 */ } + /* USER CODE END NonMaskableInt_IRQn 1 */ } - /** * @brief This function handles Memory management fault. */ diff --git a/STM32H723ZGTX_FLASH.ld b/STM32H723ZGTX_FLASH.ld index 12b8d779..db08eb36 100644 --- a/STM32H723ZGTX_FLASH.ld +++ b/STM32H723ZGTX_FLASH.ld @@ -141,6 +141,14 @@ SECTIONS the sections below it would try to be placed afterwards thus overflowing the FLASH */ + /* + This is a space to save all the related information about the hardfault + */ + .hardfault_log 0x080C0000 : + { + KEEP(*(.hardfault_log)) + . = . + 0x200; + } >FLASH .metadata_pool : { . = ABSOLUTE(0x080DFD00); From 0c0716f8936c5b708cb59e64b706b7c272ca64a6 Mon Sep 17 00:00:00 2001 From: oganigl Date: Thu, 11 Dec 2025 17:25:08 +0100 Subject: [PATCH 02/18] add the leds of the microcontroller to the runnes --- Core/Src/Runes/Runes.cpp | 4 ++-- Core/Src/main.cpp | 9 +++++++-- deps/ST-LIB | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/Core/Src/Runes/Runes.cpp b/Core/Src/Runes/Runes.cpp index 254b5a02..1e95a4cc 100644 --- a/Core/Src/Runes/Runes.cpp +++ b/Core/Src/Runes/Runes.cpp @@ -319,8 +319,8 @@ MultiplierAccelerator::FMACInstance MultiplierAccelerator::Instance = { * HARD_FAULT ***********************************************/ extern "C"{ -GPIO_TypeDef* ports_hard_fault[] = {GPIOB,GPIOB,GPIOE}; -uint16_t pins_hard_fault[] = {GPIO_PIN_0,GPIO_PIN_14,GPIO_PIN_1}; +GPIO_TypeDef* ports_hard_fault[] = {GPIOG,GPIOG,GPIOG,GPIOG}; +uint16_t pins_hard_fault[] = {GPIO_PIN_13,GPIO_PIN_12,GPIO_PIN_11,GPIO_PIN_10}; // //don't touch the count uint8_t hard_fault_leds_count = (sizeof(ports_hard_fault)/sizeof(GPIO_TypeDef*) == sizeof(pins_hard_fault)/sizeof(uint16_t)) ? sizeof(pins_hard_fault)/sizeof(uint16_t) : 0; diff --git a/Core/Src/main.cpp b/Core/Src/main.cpp index 66bc7008..e2e14f6a 100644 --- a/Core/Src/main.cpp +++ b/Core/Src/main.cpp @@ -1,13 +1,18 @@ + #include "main.h" #include "ST-LIB.hpp" + int main(void) { #ifdef SIM_ON SharedMemory::start(); #endif Hard_fault_check(); - volatile uint32_t *bad = (uint32_t*)0xFFFFFFFF; - [[maybe_unused]]uint32_t x = *bad; // dirección ilegal + DigitalOutput led_on(PB0); STLIB::start(); + + Time::register_low_precision_alarm(100, [&]() { led_on.toggle(); + }); + while (1) { STLIB::update(); } diff --git a/deps/ST-LIB b/deps/ST-LIB index dbe4a57f..4037346a 160000 --- a/deps/ST-LIB +++ b/deps/ST-LIB @@ -1 +1 @@ -Subproject commit dbe4a57f473998907e04282ab51f5c9610c15cd7 +Subproject commit 4037346aaa029714a4101e9343621abd8b3309d6 From 08d7101c8db071e6b4caa4c68a9ddc159824dd85 Mon Sep 17 00:00:00 2001 From: oganigl Date: Sat, 13 Dec 2025 11:46:31 +0100 Subject: [PATCH 03/18] eliminate leds from runes and add a config dir to keep it, also choose leds depending on the presets. --- Core/Src/Runes/Runes.cpp | 11 ----------- Core/Src/Runes/generated_metadata.cpp | 6 +++--- Core/Src/config/leds_hard_fault.cpp | 20 ++++++++++++++++++++ 3 files changed, 23 insertions(+), 14 deletions(-) create mode 100644 Core/Src/config/leds_hard_fault.cpp diff --git a/Core/Src/Runes/Runes.cpp b/Core/Src/Runes/Runes.cpp index 1e95a4cc..511a2cba 100644 --- a/Core/Src/Runes/Runes.cpp +++ b/Core/Src/Runes/Runes.cpp @@ -314,14 +314,3 @@ MultiplierAccelerator::FMACInstance MultiplierAccelerator::Instance = { .dma_write = DMA::Stream::DMA2Stream2, }; #endif - -/************************************************ - * HARD_FAULT - ***********************************************/ -extern "C"{ -GPIO_TypeDef* ports_hard_fault[] = {GPIOG,GPIOG,GPIOG,GPIOG}; -uint16_t pins_hard_fault[] = {GPIO_PIN_13,GPIO_PIN_12,GPIO_PIN_11,GPIO_PIN_10}; -// //don't touch the count -uint8_t hard_fault_leds_count = (sizeof(ports_hard_fault)/sizeof(GPIO_TypeDef*) == sizeof(pins_hard_fault)/sizeof(uint16_t)) - ? sizeof(pins_hard_fault)/sizeof(uint16_t) : 0; -} \ No newline at end of file diff --git a/Core/Src/Runes/generated_metadata.cpp b/Core/Src/Runes/generated_metadata.cpp index ed1c47f7..9cb8fb7e 100644 --- a/Core/Src/Runes/generated_metadata.cpp +++ b/Core/Src/Runes/generated_metadata.cpp @@ -5,11 +5,11 @@ extern "C"{ const char DESCRIPTION[255] __attribute__((section(".metadata_pool")))= "****************" // placeholder for beggining - "20251211T160625" // DateTime using ISO-8601 format + "20251213T114531" // DateTime using ISO-8601 format " " // alignment - "dbe4a57f" // STLIB commit + "4037346a" // STLIB commit "--------" // ADJ commit - "ab5f34fc" // Board commit + "0c0716f8" // Board commit // the '=' is used for unparsing ; } \ No newline at end of file diff --git a/Core/Src/config/leds_hard_fault.cpp b/Core/Src/config/leds_hard_fault.cpp new file mode 100644 index 00000000..3859a135 --- /dev/null +++ b/Core/Src/config/leds_hard_fault.cpp @@ -0,0 +1,20 @@ +#include "HALAL/HALAL.hpp" +extern "C"{ + +#ifdef NUCLEO +GPIO_TypeDef* ports_hard_fault[] = {GPIOB,GPIOB,GPIOE}; +uint16_t pins_hard_fault[] = {GPIO_PIN_0,GPIO_PIN_14,GPIO_PIN_1}; +// //don't touch the count +uint8_t hard_fault_leds_count = (sizeof(ports_hard_fault)/sizeof(GPIO_TypeDef*) == sizeof(pins_hard_fault)/sizeof(uint16_t)) + ? sizeof(pins_hard_fault)/sizeof(uint16_t) : 0; + +#endif + +#ifdef BOARD +GPIO_TypeDef* ports_hard_fault[] = {GPIOG,GPIOG,GPIOG,GPIOG}; +uint16_t pins_hard_fault[] = {GPIO_PIN_13,GPIO_PIN_12,GPIO_PIN_11,GPIO_PIN_10}; +// //don't touch the count +uint8_t hard_fault_leds_count = (sizeof(ports_hard_fault)/sizeof(GPIO_TypeDef*) == sizeof(pins_hard_fault)/sizeof(uint16_t)) + ? sizeof(pins_hard_fault)/sizeof(uint16_t) : 0; +#endif +} \ No newline at end of file From 52190b03000ef0b0c290028e49d6d6ea3025ec11 Mon Sep 17 00:00:00 2001 From: oganigl Date: Sat, 13 Dec 2025 11:59:12 +0100 Subject: [PATCH 04/18] eliminate the possibility of process stack pointer --- Core/Src/stm32h7xx_it.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Core/Src/stm32h7xx_it.c b/Core/Src/stm32h7xx_it.c index d54f2ab3..15d2e585 100644 --- a/Core/Src/stm32h7xx_it.c +++ b/Core/Src/stm32h7xx_it.c @@ -91,16 +91,13 @@ extern FDCAN_HandleTypeDef hfdcan1; * @brief This function handles Non maskable interrupt. */ - +//calls my_fault_handler with the MSP(main stack pointer) #define HARDFAULT_HANDLING_ASM(_x) \ __asm volatile( \ - "tst lr, #4 \n" \ - "ite eq \n" \ "mrseq r0, msp \n" \ - "mrsne r0, psp \n" \ "b my_fault_handler_c \n" \ ) -//calls my_fault_handler with the pointer frame that was being used MSP(Main stack pointer) PSP(process stack pointer) + //create the space for the hardfault section in the flash __attribute__((section(".hardfault_log"))) From b98228ab84a2ea2c7387a66321b095e6ad98b24e Mon Sep 17 00:00:00 2001 From: oganigl Date: Sat, 13 Dec 2025 12:12:56 +0100 Subject: [PATCH 05/18] minor fix --- Core/Src/Runes/generated_metadata.cpp | 6 +++--- Core/Src/stm32h7xx_it.c | 12 ++++++------ deps/ST-LIB | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Core/Src/Runes/generated_metadata.cpp b/Core/Src/Runes/generated_metadata.cpp index 9cb8fb7e..db74b032 100644 --- a/Core/Src/Runes/generated_metadata.cpp +++ b/Core/Src/Runes/generated_metadata.cpp @@ -5,11 +5,11 @@ extern "C"{ const char DESCRIPTION[255] __attribute__((section(".metadata_pool")))= "****************" // placeholder for beggining - "20251213T114531" // DateTime using ISO-8601 format + "20251213T121238" // DateTime using ISO-8601 format " " // alignment - "4037346a" // STLIB commit + "c0d7a758" // STLIB commit "--------" // ADJ commit - "0c0716f8" // Board commit + "52190b03" // Board commit // the '=' is used for unparsing ; } \ No newline at end of file diff --git a/Core/Src/stm32h7xx_it.c b/Core/Src/stm32h7xx_it.c index 15d2e585..1d1df9bb 100644 --- a/Core/Src/stm32h7xx_it.c +++ b/Core/Src/stm32h7xx_it.c @@ -94,7 +94,7 @@ extern FDCAN_HandleTypeDef hfdcan1; //calls my_fault_handler with the MSP(main stack pointer) #define HARDFAULT_HANDLING_ASM(_x) \ __asm volatile( \ - "mrseq r0, msp \n" \ + "mrs r0, msp \n" \ "b my_fault_handler_c \n" \ ) @@ -216,7 +216,7 @@ void my_fault_handler_c(sContextStateFrame *frame) { const uint16_t INVPC = usage_fault & 0x0004; //Invalid program counter load const uint16_t INVSTATE = usage_fault & 0x0002; // Invalid processor state const uint16_t UNDEFINSTR = usage_fault & 0x0001; //Undefined instruction. - //HALT_IF_DEBUGGING(); + HALT_IF_DEBUGGING(); } volatile uint8_t metadata_buffer[0x100]; memcpy(metadata_buffer,(void*)METADATA_FLASH_ADDR,0x100); @@ -226,10 +226,10 @@ void my_fault_handler_c(sContextStateFrame *frame) { //write log Metadata_flash_addr flash_write_blockwise(METADATA_FLASH_ADDR,metadata_buffer,(0x100)/32); //reboot the system - volatile uint32_t *aircr = (volatile uint32_t *)0xE000ED0C; - __asm volatile ("dsb"); - *aircr = (0x05FA << 16) | 0x1 << 2; - __asm volatile ("dsb"); + // volatile uint32_t *aircr = (volatile uint32_t *)0xE000ED0C; + // __asm volatile ("dsb"); + // *aircr = (0x05FA << 16) | 0x1 << 2; + // __asm volatile ("dsb"); while (1) {} // should be unreachable } diff --git a/deps/ST-LIB b/deps/ST-LIB index 4037346a..c0d7a758 160000 --- a/deps/ST-LIB +++ b/deps/ST-LIB @@ -1 +1 @@ -Subproject commit 4037346aaa029714a4101e9343621abd8b3309d6 +Subproject commit c0d7a758638ca31511f1d4791cc796cb0ed1a05d From f6f533d3b18c44d54b3be793eaa24ee423d70b12 Mon Sep 17 00:00:00 2001 From: oganigl Date: Sat, 13 Dec 2025 16:53:23 +0100 Subject: [PATCH 06/18] added -g to add more debug info also in release so Is possible to know the address of the hardfault --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 44b7ec84..de34048d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,7 +54,7 @@ target_compile_options(${EXECUTABLE} PRIVATE $<$:-mfloat-abi=hard> $<$:-mthumb> $<$:-specs=nosys.specs> - + -g -ffunction-sections -fdata-sections -fno-exceptions From 6bfbb5bed4f1b2ec340811cb70f8bee64d67940d Mon Sep 17 00:00:00 2001 From: oganigl Date: Sat, 13 Dec 2025 17:23:39 +0100 Subject: [PATCH 07/18] create a script to read the flash and give feedback about the hard_fault --- hard_faullt_analysis.py | 187 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 hard_faullt_analysis.py diff --git a/hard_faullt_analysis.py b/hard_faullt_analysis.py new file mode 100644 index 00000000..f4185225 --- /dev/null +++ b/hard_faullt_analysis.py @@ -0,0 +1,187 @@ +import subprocess +import struct +import re +import os +HF_FLASH_ADDR = 0x080C0000 +HF_FLASH_ADDR_STRING = "0x080C000" +ELF_FILE = "out/build/latest.elf" + +def read_flash(): + cmd = [ + "STM32_Programmer_CLI", + "-c", "port=SWD", + "-r32", hex(HF_FLASH_ADDR), "44" + ] + out = subprocess.check_output(cmd, text=True) + return out + +def decode_cfsr_memory(cfsr, fault_addr): + memory_fault = cfsr & 0xFF + if memory_fault == 0: + return + print("\nMemory Fault (MMFSR):") + if memory_fault & 0b10000000: + print(f" MMARVALID: Memory fault address valid -> 0x{fault_addr:08X}") + if memory_fault & 0b00100000: + print(" MLSPERR : Floating Point Unit lazy state preservation error") + if memory_fault & 0b00010000: + print(" MSTKERR : Stack error on entry to exception") + if memory_fault & 0b00001000: + print(" MUNSTKERR : Stack error on return from exception") + if memory_fault & 0b00000010: + print(" DACCVIOL : Data access violation (NULL pointer or invalid access)") + if memory_fault & 0b00000001: + print(" IACCVIOL : Instruction access violation") + + +# -------------------------- +# Decode Bus Fault (BFSR) +# -------------------------- +def decode_cfsr_bus(cfsr, fault_addr): + bus_fault = (cfsr & 0x0000FF00) >> 8 + if bus_fault == 0: + return + print("\nBus Fault (BFSR):") + if bus_fault & 0b10000000: + if(bus_fault & 0b00000001): + print(f" BFARVALID : Bus fault address valid -> 0x{fault_addr:08X}") + else: + print(f" BFARVALID : Bus fault address imprecise -> 0x{fault_addr:08X}") + if bus_fault & 0b00100000: + print(" LSPERR : Floating Point Unit lazy state preservation error") + if bus_fault & 0b00010000: + print(" STKERR : Stack error on entry to exception") + if bus_fault & 0b00001000: + print(" UNSTKERR : Stack error on return from exception") + + +# -------------------------- +# Decode Usage Fault (UFSR) +# -------------------------- +def decode_cfsr_usage(cfsr): + usage_fault = (cfsr & 0xFFFF0000) >> 16 + if usage_fault == 0: + return + print("\nUsage Fault (UFSR):") + if usage_fault & 0x0200: + print(" DIVBYZERO : Division by zero") + if usage_fault & 0x0100: + print(" UNALIGNED : Unaligned memory access") + if usage_fault & 0x0008: + print(" NOCP : Accessed FPU when not present") + if usage_fault & 0x0004: + print(" INVPC : Invalid Program Counter(PC) load") + if usage_fault & 0x0002: + print(" INVSTATE : Invalid processor state") + if usage_fault & 0x0001: + print(" UNDEFINSTR : Undefined instruction") + + +def decode_cfsr(cfsr, fault_addr): + decode_cfsr_memory(cfsr, fault_addr) + decode_cfsr_bus(cfsr, fault_addr) + decode_cfsr_usage(cfsr) + + +def addr2line(addr): + cmd = ["arm-none-eabi-addr2line", "-e", ELF_FILE, "-f", "-C", hex(addr)] + try: + output = subprocess.check_output(cmd, text=True).strip() + return output + except Exception as e: + return f"addr2line failed: {e}" + +def print_code_context(lines, context=2): + """ + lines: salida de addr2line (función + file:line) + context: cuántas líneas arriba/abajo mostrar + """ + line_list = lines.splitlines() + if len(line_list) < 2: + print("Invalid addr2line output") + return + + file_line = line_list[1].strip() # ejemplo: /path/to/file.cpp:5 + split = file_line.rfind(':') + file_path = file_line[:split] + line_no = int(file_line[split+1:]) - 1 # índice base 0 + + if not os.path.exists(file_path): + print("Source file not found") + return + + with open(file_path, "r") as f: + file_lines = f.readlines() + + start = max(0, line_no - context) + end = min(len(file_lines), line_no + context + 1) + + print(f"\nSource snippet from {file_path}:") + for i in range(start, end): + code = file_lines[i].rstrip() + # Si es la línea del error, la ponemos en rojo + if i == line_no: + print(f"\033[91m{i+1:>4}: {code}\033[0m") # rojo + else: + print(f"{i+1:>4}: {code}") + +def hard_fault_analysis(memory_string): + raw = bytes.fromhex(memory_string) + raw = struct.unpack(">11I",raw) + hf = { + "HF_Flag": raw[0], + "r0": raw[1], + "r1": raw[2], + "r2": raw[3], + "r3": raw[4], + "r12": raw[5], + "lr": raw[6], + "pc":raw[7], + "psr": raw[8], + "cfsr":raw[9], + "fault_addr":raw[10] + } + print(F"raw : {hf["HF_Flag"]}") + if(hf["HF_Flag"] != 0xFF00FF00): + print("There was no hardfault in your Microcontroller, Kudos for you, I hope...") + return + print("================HARDFAULT DETECTED ===========") + print("Registers:") + + for r in ['r0','r1','r2','r3','r12','lr','pc','psr']: + print(f" {r.upper():<4}: 0x{hf[r]:08X}") + + print(f" CFSR: 0x{hf['cfsr']:08X}") + decode_cfsr(hf["cfsr"], hf["fault_addr"]) + print("\nSource Location:") + pc_loc = addr2line(hf["pc"]) + lr_loc = addr2line(hf["lr"]) + print(f" Linker Register : 0x{hf['lr']:08X} -> {lr_loc}") + + print(f" Program Counter : 0x{hf['pc']:08X} -> {pc_loc}") + print_code_context(pc_loc) + + + print("======================================================") + + + print("Note: In Release builds (-O2/-O3) the PC may not point exactly to the failing instruction.") + print(" During interrupts, bus faults, or stack corruption, the PC can be imprecise.") + print(" Use the LR and stack frame for better context of where the fault originated.") + +if __name__ == '__main__': + out = read_flash() + pos_memory_flash = out.rfind(HF_FLASH_ADDR_STRING) + print(out[0:pos_memory_flash]) + flash = out[pos_memory_flash:] + print(flash) + memory_string = "" + for line in flash.splitlines(): + if(line.find(':') == -1): + break + _,mem = line.split(":") + memory_string += mem + memory_string = memory_string.replace(" ","") + print(memory_string) + hard_fault_analysis(memory_string) + From 1ca659a1d82150af89c27826fd50e5d265174fdc Mon Sep 17 00:00:00 2001 From: oganigl Date: Sat, 13 Dec 2025 17:24:10 +0100 Subject: [PATCH 08/18] minor change in hard_fault_handler --- Core/Src/stm32h7xx_it.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Core/Src/stm32h7xx_it.c b/Core/Src/stm32h7xx_it.c index 1d1df9bb..e39122b1 100644 --- a/Core/Src/stm32h7xx_it.c +++ b/Core/Src/stm32h7xx_it.c @@ -163,19 +163,15 @@ static int hardfault_flag_is_set(void){ } while (0) //Breakpoint in debug mode - -volatile uint32_t real_fault_pc; __attribute__((noreturn,optimize("O0"))) void my_fault_handler_c(sContextStateFrame *frame) { - // If and only if a debugger is attached, execute a breakpoint - // instruction so we can take a look at what triggered the fault - const uint32_t instr_pc = frame->return_address; - real_fault_pc = instr_pc & ~1; //clean bit 0, real direction + volatile uint32_t real_fault_pc = frame->return_address & ~1; volatile HardFaultLog log_hard_fault; volatile uint32_t *cfsr = (volatile uint32_t *)0xE000ED28; //keep the log in the estructure log_hard_fault.HF_flag = HF_FLAG_VALUE; log_hard_fault.frame = *frame; + log_hard_fault.frame.return_address = real_fault_pc; log_hard_fault.CfsrDecode.cfsr = *cfsr; log_hard_fault.fault_address.Nothing_Valid = 0; From 48585ba7742d702f7caaadc613c9614c6d964db7 Mon Sep 17 00:00:00 2001 From: oganigl Date: Sat, 13 Dec 2025 17:31:48 +0100 Subject: [PATCH 09/18] eliminate break points from debug mode --- Core/Src/stm32h7xx_it.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/Core/Src/stm32h7xx_it.c b/Core/Src/stm32h7xx_it.c index e39122b1..50c2db69 100644 --- a/Core/Src/stm32h7xx_it.c +++ b/Core/Src/stm32h7xx_it.c @@ -155,13 +155,6 @@ static int hardfault_flag_is_set(void){ return (*(volatile uint32_t *)HF_FLASH_ADDR) == HF_FLAG_VALUE; } -#define HALT_IF_DEBUGGING() \ - do { \ - if ((*(volatile uint32_t *)0xE000EDF0) & (1 << 0)) { \ - __asm("bkpt 1"); \ - } \ - } while (0) - //Breakpoint in debug mode __attribute__((noreturn,optimize("O0"))) void my_fault_handler_c(sContextStateFrame *frame) { @@ -187,7 +180,6 @@ void my_fault_handler_c(sContextStateFrame *frame) { uint32_t memory_fault_address = *(volatile uint32_t *)0xE000ED34; log_hard_fault.fault_address.MMAR_VALID = memory_fault_address; } - HALT_IF_DEBUGGING(); } const uint8_t bus_fault = (*cfsr & 0x0000ff00) >> 8; if(bus_fault){ @@ -202,7 +194,6 @@ void my_fault_handler_c(sContextStateFrame *frame) { log_hard_fault.fault_address.BFAR_VALID = bus_fault_address; //Don't trust in case IMPRECISERR == 1; } - HALT_IF_DEBUGGING(); } const uint16_t usage_fault = (*cfsr & 0xffff0000) >> 16; if(usage_fault){ @@ -212,7 +203,6 @@ void my_fault_handler_c(sContextStateFrame *frame) { const uint16_t INVPC = usage_fault & 0x0004; //Invalid program counter load const uint16_t INVSTATE = usage_fault & 0x0002; // Invalid processor state const uint16_t UNDEFINSTR = usage_fault & 0x0001; //Undefined instruction. - HALT_IF_DEBUGGING(); } volatile uint8_t metadata_buffer[0x100]; memcpy(metadata_buffer,(void*)METADATA_FLASH_ADDR,0x100); @@ -222,10 +212,10 @@ void my_fault_handler_c(sContextStateFrame *frame) { //write log Metadata_flash_addr flash_write_blockwise(METADATA_FLASH_ADDR,metadata_buffer,(0x100)/32); //reboot the system - // volatile uint32_t *aircr = (volatile uint32_t *)0xE000ED0C; - // __asm volatile ("dsb"); - // *aircr = (0x05FA << 16) | 0x1 << 2; - // __asm volatile ("dsb"); + volatile uint32_t *aircr = (volatile uint32_t *)0xE000ED0C; + __asm volatile ("dsb"); + *aircr = (0x05FA << 16) | 0x1 << 2; + __asm volatile ("dsb"); while (1) {} // should be unreachable } From bfbe84e528d1843179651a4e42772e5e5ef31288 Mon Sep 17 00:00:00 2001 From: oganigl Date: Sat, 13 Dec 2025 23:18:09 +0100 Subject: [PATCH 10/18] eliminate a print that was not need it --- hard_faullt_analysis.py | 1 - 1 file changed, 1 deletion(-) diff --git a/hard_faullt_analysis.py b/hard_faullt_analysis.py index f4185225..6913f38f 100644 --- a/hard_faullt_analysis.py +++ b/hard_faullt_analysis.py @@ -141,7 +141,6 @@ def hard_fault_analysis(memory_string): "cfsr":raw[9], "fault_addr":raw[10] } - print(F"raw : {hf["HF_Flag"]}") if(hf["HF_Flag"] != 0xFF00FF00): print("There was no hardfault in your Microcontroller, Kudos for you, I hope...") return From b202b1bef8be01cca2bb757f06b7e5b4053dbdd0 Mon Sep 17 00:00:00 2001 From: oganigl Date: Tue, 20 Jan 2026 14:16:53 +0100 Subject: [PATCH 11/18] add a function to scan the call stack --- .vscode/settings.json | 2 +- Core/Src/Runes/generated_metadata.cpp | 6 +-- Core/Src/main.cpp | 67 +++++++++++++++++++++++---- Core/Src/stm32h7xx_it.c | 48 +++++++++++++++---- STM32H723ZGTX_FLASH.ld | 6 ++- STM32H723ZGTX_RAM.ld | 2 + deps/ST-LIB | 2 +- hard_faullt_analysis.py | 41 ++++++++++------ tools/retrieve_flash_data.py | 4 +- 9 files changed, 136 insertions(+), 42 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 0126b4a8..66a250fa 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -25,5 +25,5 @@ "shared_mutex": "cpp", "regex": "cpp" }, - "cortex-debug.variableUseNaturalFormat": true + "cortex-debug.variableUseNaturalFormat": false } diff --git a/Core/Src/Runes/generated_metadata.cpp b/Core/Src/Runes/generated_metadata.cpp index db74b032..db32ac39 100644 --- a/Core/Src/Runes/generated_metadata.cpp +++ b/Core/Src/Runes/generated_metadata.cpp @@ -5,11 +5,11 @@ extern "C"{ const char DESCRIPTION[255] __attribute__((section(".metadata_pool")))= "****************" // placeholder for beggining - "20251213T121238" // DateTime using ISO-8601 format + "20260120T141051" // DateTime using ISO-8601 format " " // alignment - "c0d7a758" // STLIB commit + "6266c183" // STLIB commit "--------" // ADJ commit - "52190b03" // Board commit + "bfbe84e5" // Board commit // the '=' is used for unparsing ; } \ No newline at end of file diff --git a/Core/Src/main.cpp b/Core/Src/main.cpp index e2e14f6a..c914cb1a 100644 --- a/Core/Src/main.cpp +++ b/Core/Src/main.cpp @@ -1,23 +1,70 @@ #include "main.h" #include "ST-LIB.hpp" +#include "stm32h7xx_hal.h" +#include "core_cm7.h" -int main(void) { -#ifdef SIM_ON - SharedMemory::start(); -#endif +// void enable_mpu(void) { +// MPU_Region_InitTypeDef MPU_InitStruct; + +// HAL_MPU_Disable(); + +// MPU_InitStruct.Enable = MPU_REGION_ENABLE; +// MPU_InitStruct.BaseAddress = 0x20000000; // SRAM1 +// MPU_InitStruct.Size = MPU_REGION_SIZE_256KB; +// MPU_InitStruct.AccessPermission = MPU_REGION_NO_ACCESS; +// MPU_InitStruct.IsBufferable = 0; +// MPU_InitStruct.IsCacheable = 0; +// MPU_InitStruct.IsShareable = 0; +// MPU_InitStruct.Number = MPU_REGION_NUMBER0; +// MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0; +// MPU_InitStruct.SubRegionDisable = 0x00; +// MPU_InitStruct.DisableExec = 0; + +// HAL_MPU_ConfigRegion(&MPU_InitStruct); + +// HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT); +// } + +// int main(void) { +// #ifdef SIM_ON +// SharedMemory::start(); +// #endif +// Hard_fault_check(); +// HAL_Init(); +// enable_mpu(); +// DigitalOutput led_on(PB0); +// volatile uint32_t *ptr = (uint32_t*)0x20000000; // SRAM1, pero NO accesible +// *ptr = 0xABCD; // MemManage Fault +// STLIB::start(); +// Time::register_low_precision_alarm(100, [&]() { led_on.toggle(); +// }); + +// while (1) { +// STLIB::update(); +// } +// } +static void enable_div0_trap(void) +{ + SCB->CCR |= SCB_CCR_DIV_0_TRP_Msk; +} + +int main(void) +{ Hard_fault_check(); - DigitalOutput led_on(PB0); - STLIB::start(); + HAL_Init(); - Time::register_low_precision_alarm(100, [&]() { led_on.toggle(); - }); + enable_div0_trap(); + volatile int a = 10; + volatile int b = 0; + volatile int c; + + c = a / b; + a = c; while (1) { - STLIB::update(); } } - void Error_Handler(void) { ErrorHandler("HAL error handler triggered"); while (1) { diff --git a/Core/Src/stm32h7xx_it.c b/Core/Src/stm32h7xx_it.c index 50c2db69..08283751 100644 --- a/Core/Src/stm32h7xx_it.c +++ b/Core/Src/stm32h7xx_it.c @@ -80,6 +80,13 @@ extern TIM_HandleTypeDef htim8; extern TIM_HandleTypeDef htim23; extern TIM_HandleTypeDef htim24; extern FDCAN_HandleTypeDef hfdcan1; +/* +Externs for calltrace +*/ +extern uint32_t _stext; +extern uint32_t _etext; +extern uint32_t _sstack; +extern uint32_t _estack; /* USER CODE BEGIN EV */ /* USER CODE END EV */ @@ -154,12 +161,36 @@ static void flash_erase_hard_fault_sector(void){ static int hardfault_flag_is_set(void){ return (*(volatile uint32_t *)HF_FLASH_ADDR) == HF_FLAG_VALUE; } +static uint8_t is_valid_pc(uint32_t pc) +{ + pc &= ~1U; // Thumb + return (pc >= (uint32_t)&_stext && + pc < (uint32_t)&_etext); +} +static void scan_call_stack(sContextStateFrame *frame, HardFaultLog *log_hard_fault) +{ + uint32_t *stack_start = (uint32_t *)&_sstack; + uint32_t *stack_end = (uint32_t *)&_estack; + log_hard_fault->CallTrace.depth = 0; + uint32_t *sp = (uint32_t *)(frame + 1); + while (sp < stack_end && sp >= stack_start) + { + uint32_t val = *sp++; + if (log_hard_fault->CallTrace.depth >= CALL_TRACE_MAX_DEPTH) break; + if ((val & 1U) == 0) continue; + if (!is_valid_pc(val)) continue; + log_hard_fault->CallTrace.pcs[log_hard_fault->CallTrace.depth++] = val & ~1U; + } +} __attribute__((noreturn,optimize("O0"))) void my_fault_handler_c(sContextStateFrame *frame) { volatile uint32_t real_fault_pc = frame->return_address & ~1; volatile HardFaultLog log_hard_fault; + + scan_call_stack(frame,&log_hard_fault); + volatile uint32_t *cfsr = (volatile uint32_t *)0xE000ED28; //keep the log in the estructure log_hard_fault.HF_flag = HF_FLAG_VALUE; @@ -208,7 +239,9 @@ void my_fault_handler_c(sContextStateFrame *frame) { memcpy(metadata_buffer,(void*)METADATA_FLASH_ADDR,0x100); flash_erase_hard_fault_sector(); //write log hard fault + volatile uint8_t hardfault_buffer[0x100]; flash_write_blockwise(HF_FLASH_ADDR,(uint8_t*)&log_hard_fault,(sizeof(log_hard_fault) + 31)/32); + memcpy(hardfault_buffer,(void*)HF_FLASH_ADDR,0X200); //write log Metadata_flash_addr flash_write_blockwise(METADATA_FLASH_ADDR,metadata_buffer,(0x100)/32); //reboot the system @@ -241,16 +274,13 @@ void NMI_Handler(void) */ void MemManage_Handler(void) { - /* USER CODE BEGIN MemoryManagement_IRQn 0 */ - - /* USER CODE END MemoryManagement_IRQn 0 */ - while (1) - { - /* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */ - /* USER CODE END W1_MemoryManagement_IRQn 0 */ + extern void my_fault_handler_c(sContextStateFrame *frame); + + __asm volatile( + "mrs r0, msp\n" // obtener stack frame + "b my_fault_handler_c\n" + ); } -} - /** * @brief This function handles Pre-fetch fault, memory access fault. */ diff --git a/STM32H723ZGTX_FLASH.ld b/STM32H723ZGTX_FLASH.ld index db08eb36..9c4d227d 100644 --- a/STM32H723ZGTX_FLASH.ld +++ b/STM32H723ZGTX_FLASH.ld @@ -35,6 +35,7 @@ ENTRY(Reset_Handler) /* Highest address of the user mode stack */ +_sstack = ORIGIN(RAM_D1); _estack = ORIGIN(RAM_D1) + LENGTH(RAM_D1); /* end of RAM */ /* Generate a link error if heap and stack don't fit into RAM */ _Min_Heap_Size = 0x200; /* required amount of heap */ @@ -66,6 +67,7 @@ SECTIONS .text : { . = ALIGN(4); + _stext = .; *(.text) /* .text sections (code) */ *(.text*) /* .text* sections (code) */ *(.glue_7) /* glue arm to thumb code */ @@ -149,9 +151,9 @@ SECTIONS KEEP(*(.hardfault_log)) . = . + 0x200; } >FLASH - .metadata_pool : + + .metadata_pool 0x080DFD00: { - . = ABSOLUTE(0x080DFD00); . = ALIGN(4); metadata = .; KEEP(*(.metadata_pool)) diff --git a/STM32H723ZGTX_RAM.ld b/STM32H723ZGTX_RAM.ld index 4d2e09c4..56dab088 100644 --- a/STM32H723ZGTX_RAM.ld +++ b/STM32H723ZGTX_RAM.ld @@ -35,6 +35,7 @@ ENTRY(Reset_Handler) /* Highest address of the user mode stack */ +_sstack = ORIGIN(DTCMRAM); _estack = ORIGIN(DTCMRAM) + LENGTH(DTCMRAM); /* end of RAM */ /* Generate a link error if heap and stack don't fit into RAM */ _Min_Heap_Size = 0x200 ; /* required amount of heap */ @@ -65,6 +66,7 @@ SECTIONS .text : { . = ALIGN(4); + _stext = .; *(.text) /* .text sections (code) */ *(.text*) /* .text* sections (code) */ *(.glue_7) /* glue arm to thumb code */ diff --git a/deps/ST-LIB b/deps/ST-LIB index c0d7a758..6266c183 160000 --- a/deps/ST-LIB +++ b/deps/ST-LIB @@ -1 +1 @@ -Subproject commit c0d7a758638ca31511f1d4791cc796cb0ed1a05d +Subproject commit 6266c1831a7e223a9b505d4ed479f355059ac6a0 diff --git a/hard_faullt_analysis.py b/hard_faullt_analysis.py index 6913f38f..5b852019 100644 --- a/hard_faullt_analysis.py +++ b/hard_faullt_analysis.py @@ -6,11 +6,12 @@ HF_FLASH_ADDR_STRING = "0x080C000" ELF_FILE = "out/build/latest.elf" +CALL_TRACE_MAX_DEPTH = 16 def read_flash(): cmd = [ "STM32_Programmer_CLI", "-c", "port=SWD", - "-r32", hex(HF_FLASH_ADDR), "44" + "-r32", hex(HF_FLASH_ADDR), "112" ] out = subprocess.check_output(cmd, text=True) return out @@ -22,6 +23,11 @@ def decode_cfsr_memory(cfsr, fault_addr): print("\nMemory Fault (MMFSR):") if memory_fault & 0b10000000: print(f" MMARVALID: Memory fault address valid -> 0x{fault_addr:08X}") + if fault_addr in (0xFFFFFFFF, 0x00000000): + print(" Fault address is invalid / unmapped memory") + else: + mem_info = addr2line(fault_addr) + print_code_context(mem_info) if memory_fault & 0b00100000: print(" MLSPERR : Floating Point Unit lazy state preservation error") if memory_fault & 0b00010000: @@ -45,8 +51,8 @@ def decode_cfsr_bus(cfsr, fault_addr): if bus_fault & 0b10000000: if(bus_fault & 0b00000001): print(f" BFARVALID : Bus fault address valid -> 0x{fault_addr:08X}") - else: - print(f" BFARVALID : Bus fault address imprecise -> 0x{fault_addr:08X}") + if bus_fault & 0b00000100: + print(f"\033[91m Bus fault address imprecise\033[0m") if bus_fault & 0b00100000: print(" LSPERR : Floating Point Unit lazy state preservation error") if bus_fault & 0b00010000: @@ -101,13 +107,16 @@ def print_code_context(lines, context=2): print("Invalid addr2line output") return - file_line = line_list[1].strip() # ejemplo: /path/to/file.cpp:5 + file_line = line_list[1].strip() split = file_line.rfind(':') file_path = file_line[:split] - line_no = int(file_line[split+1:]) - 1 # índice base 0 - - if not os.path.exists(file_path): - print("Source file not found") + try: + line_no = int(file_line[split+1:]) - 1 # índice base 0 + except ValueError: + print("\33[91m Couldn't find exact line\33[0m") + return + if not os.path.exists(file_path): + print("Source file not found") return with open(file_path, "r") as f: @@ -127,7 +136,7 @@ def print_code_context(lines, context=2): def hard_fault_analysis(memory_string): raw = bytes.fromhex(memory_string) - raw = struct.unpack(">11I",raw) + raw = struct.unpack(">28I",raw) hf = { "HF_Flag": raw[0], "r0": raw[1], @@ -136,10 +145,12 @@ def hard_fault_analysis(memory_string): "r3": raw[4], "r12": raw[5], "lr": raw[6], - "pc":raw[7], + "pc": raw[7], "psr": raw[8], - "cfsr":raw[9], - "fault_addr":raw[10] + "cfsr": raw[9], + "fault_addr": raw[10], + "calltrace_depth": raw[11], + "calltrace_pcs": raw[12:28] } if(hf["HF_Flag"] != 0xFF00FF00): print("There was no hardfault in your Microcontroller, Kudos for you, I hope...") @@ -166,7 +177,10 @@ def hard_fault_analysis(memory_string): print("Note: In Release builds (-O2/-O3) the PC may not point exactly to the failing instruction.") print(" During interrupts, bus faults, or stack corruption, the PC can be imprecise.") - print(" Use the LR and stack frame for better context of where the fault originated.") + print("\nIn case of Imprecise error is dificult to find due to is asynchronous fault") + print("The error has to be before PC. But not possible to know exactly when.") + print("Check this link to know more : https://interrupt.memfault.com/blog/cortex-m-hardfault-debug#fn:8") + if __name__ == '__main__': out = read_flash() @@ -181,6 +195,5 @@ def hard_fault_analysis(memory_string): _,mem = line.split(":") memory_string += mem memory_string = memory_string.replace(" ","") - print(memory_string) hard_fault_analysis(memory_string) diff --git a/tools/retrieve_flash_data.py b/tools/retrieve_flash_data.py index 1ebf07d9..9d9dbf3c 100644 --- a/tools/retrieve_flash_data.py +++ b/tools/retrieve_flash_data.py @@ -23,8 +23,8 @@ def main(): exit(-1) binary_raw = None - - with open("dump.bin","r") as binary: + with open("dump.bin","rb") as binary: + binary_raw = binary.read() #DEFINITIONS FOR LOCATIONS From 9d3d6286b3d4678b9a8aa09f85f54d263f679067 Mon Sep 17 00:00:00 2001 From: oganigl Date: Tue, 20 Jan 2026 16:36:27 +0100 Subject: [PATCH 12/18] finish hard_fault, the call stack trace done, it show also irrevelant info, but can be useful --- Core/Src/Runes/generated_metadata.cpp | 4 +- Core/Src/main.cpp | 81 ++++++--------- Core/Src/stm32h7xx_it.c | 137 ++++++++++++++------------ STM32H723ZGTX_FLASH.ld | 14 ++- STM32H723ZGTX_RAM.ld | 11 +++ hard_faullt_analysis.py | 87 ++++++++++++---- 6 files changed, 195 insertions(+), 139 deletions(-) diff --git a/Core/Src/Runes/generated_metadata.cpp b/Core/Src/Runes/generated_metadata.cpp index db32ac39..94cda75d 100644 --- a/Core/Src/Runes/generated_metadata.cpp +++ b/Core/Src/Runes/generated_metadata.cpp @@ -5,11 +5,11 @@ extern "C"{ const char DESCRIPTION[255] __attribute__((section(".metadata_pool")))= "****************" // placeholder for beggining - "20260120T141051" // DateTime using ISO-8601 format + "20260120T161715" // DateTime using ISO-8601 format " " // alignment "6266c183" // STLIB commit "--------" // ADJ commit - "bfbe84e5" // Board commit + "b202b1be" // Board commit // the '=' is used for unparsing ; } \ No newline at end of file diff --git a/Core/Src/main.cpp b/Core/Src/main.cpp index c914cb1a..2cf182d8 100644 --- a/Core/Src/main.cpp +++ b/Core/Src/main.cpp @@ -4,67 +4,44 @@ #include "stm32h7xx_hal.h" #include "core_cm7.h" -// void enable_mpu(void) { -// MPU_Region_InitTypeDef MPU_InitStruct; -// HAL_MPU_Disable(); - -// MPU_InitStruct.Enable = MPU_REGION_ENABLE; -// MPU_InitStruct.BaseAddress = 0x20000000; // SRAM1 -// MPU_InitStruct.Size = MPU_REGION_SIZE_256KB; -// MPU_InitStruct.AccessPermission = MPU_REGION_NO_ACCESS; -// MPU_InitStruct.IsBufferable = 0; -// MPU_InitStruct.IsCacheable = 0; -// MPU_InitStruct.IsShareable = 0; -// MPU_InitStruct.Number = MPU_REGION_NUMBER0; -// MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0; -// MPU_InitStruct.SubRegionDisable = 0x00; -// MPU_InitStruct.DisableExec = 0; - -// HAL_MPU_ConfigRegion(&MPU_InitStruct); - -// HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT); -// } - -// int main(void) { -// #ifdef SIM_ON -// SharedMemory::start(); -// #endif -// Hard_fault_check(); -// HAL_Init(); -// enable_mpu(); -// DigitalOutput led_on(PB0); -// volatile uint32_t *ptr = (uint32_t*)0x20000000; // SRAM1, pero NO accesible -// *ptr = 0xABCD; // MemManage Fault -// STLIB::start(); -// Time::register_low_precision_alarm(100, [&]() { led_on.toggle(); -// }); - -// while (1) { -// STLIB::update(); -// } -// } -static void enable_div0_trap(void) -{ - SCB->CCR |= SCB_CCR_DIV_0_TRP_Msk; +void usage_fault_example(void) { + __builtin_trap(); +} +void func(){ + usage_fault_example(); +} +void f(){ + func(); +} +void a(){ + f(); +} +void busfault_example(void){ + *(uint32_t *)0xdead0000 = 0x20; +} +void memmanage_example(void) { + void (*fn_in_xn_region)(void) = (void (*)(void))0xE0000000; + fn_in_xn_region(); } -int main(void) -{ +int main(void) { +#ifdef SIM_ON + SharedMemory::start(); +#endif Hard_fault_check(); + a(); HAL_Init(); + DigitalOutput led_on(PB0); + STLIB::start(); + Time::register_low_precision_alarm(100, [&]() { led_on.toggle(); + }); - enable_div0_trap(); - - volatile int a = 10; - volatile int b = 0; - volatile int c; - - c = a / b; - a = c; while (1) { + STLIB::update(); } } + void Error_Handler(void) { ErrorHandler("HAL error handler triggered"); while (1) { diff --git a/Core/Src/stm32h7xx_it.c b/Core/Src/stm32h7xx_it.c index 08283751..717a4358 100644 --- a/Core/Src/stm32h7xx_it.c +++ b/Core/Src/stm32h7xx_it.c @@ -20,6 +20,7 @@ /* Includes ------------------------------------------------------------------*/ #include "main.h" #include "stm32h7xx_it.h" +#include "stm32h7xx_hal.h" #include "HALAL/Benchmarking_toolkit/HardfaultTrace.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ @@ -87,6 +88,8 @@ extern uint32_t _stext; extern uint32_t _etext; extern uint32_t _sstack; extern uint32_t _estack; +extern uint32_t _hf_stack_start; +extern uint32_t _hf_stack_end; /* USER CODE BEGIN EV */ /* USER CODE END EV */ @@ -99,67 +102,81 @@ extern uint32_t _estack; */ //calls my_fault_handler with the MSP(main stack pointer) -#define HARDFAULT_HANDLING_ASM(_x) \ - __asm volatile( \ - "mrs r0, msp \n" \ - "b my_fault_handler_c \n" \ - ) +#define HARDFAULT_HANDLING_ASM() \ +__asm volatile( \ + /* Detect which stack was in use */ \ + "tst lr, #4 \n" \ + "ite eq \n" \ + "mrseq r0, msp \n" \ + "mrsne r0, psp \n" \ + \ + /* Switch to dedicated HardFault stack */ \ + "ldr r1, =_hf_stack_end \n" \ + "msr msp, r1 \n" \ + "isb \n" \ + \ + /* Call C handler with original frame */ \ + "b my_fault_handler_c \n" \ +) //create the space for the hardfault section in the flash __attribute__((section(".hardfault_log"))) volatile uint32_t hard_fault[128]; -static void flash_unlock(void){ - if((FLASH->CR1 & FLASH_CR_LOCK) != 0){ - FLASH->KEYR1 = FLASH_KEY1; - FLASH->KEYR1 = FLASH_KEY2; +void hardfault_flash_write( + uint32_t addr_hard_fault, const void *data_hard_fault, size_t len_hard_fault, + uint32_t addr_metadata, const void *data_metadata, size_t len_metadata) +{ + __disable_irq(); + HAL_FLASH_Unlock(); + + // Erase sector + FLASH_EraseInitTypeDef erase; + uint32_t sector_error = 0; + erase.TypeErase = FLASH_TYPEERASE_SECTORS; + erase.Banks = FLASH_BANK_1; + erase.Sector = FLASH_SECTOR_6; + erase.NbSectors = 1; + erase.VoltageRange = FLASH_VOLTAGE_RANGE_3; + + if(HAL_FLASHEx_Erase(&erase, §or_error) != HAL_OK){ + __BKPT(0); } -} -static void flash_lock(void){ - FLASH->CR1 |= FLASH_CR_LOCK; -} -static void flash_wait(void){ - while(FLASH->SR1 & FLASH_SR_QW){} -} -static void flash_write_32bytes(uint32_t address,const uint8_t* data){ - if(address & 0X3U){ - return; // the address direction must be aligned 4; - } - flash_wait(); - flash_unlock(); - FLASH->CR1 |= FLASH_CR_PG; //Enable writing - for(volatile size_t i = 0; i < 8; i++){ - *(volatile uint32_t*)(address + i*4) = ((uint32_t*)data)[i]; - } - flash_wait(); - //Disable writing - FLASH->CR1 &= ~FLASH_CR_PG; - flash_lock(); -} -static void flash_write_blockwise(uint32_t address, const uint8_t *data,size_t blocks){ - for(volatile size_t i = 0; i < blocks;i++){ - flash_write_32bytes(address + i*32,data + i*32); + + + size_t offset, copy_len; + uint8_t block[32]; + + offset = 0; + while(offset < len_hard_fault){ + memset(block, 0xFF, sizeof(block)); + copy_len = (len_hard_fault - offset) > 32 ? 32 : (len_hard_fault - offset); + memcpy(block, (uint8_t*)data_hard_fault + offset, copy_len); + + if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD, addr_hard_fault + offset, (uint32_t*)block) != HAL_OK){ + __BKPT(0); + } + offset += 32; } -} -// //erase hard_fault sector 6 -static void flash_erase_hard_fault_sector(void){ - flash_wait(); - FLASH->CCR1 = 0xFFFFFFFFu; - flash_unlock(); - - FLASH->CR1 |= FLASH_CR_SER | (FLASH_SECTOR_6 << FLASH_CR_SNB_Pos); - //start erase - FLASH->CR1 |= FLASH_CR_START; - flash_wait(); - FLASH->CCR1 = 0xFFFFFFFFU; - // Clean flag - FLASH->CR1 &= ~FLASH_CR_SER; - flash_lock(); -} -//check if we have already write. -static int hardfault_flag_is_set(void){ - return (*(volatile uint32_t *)HF_FLASH_ADDR) == HF_FLAG_VALUE; + + offset = 0; + while(offset < len_metadata){ + memset(block, 0xFF, sizeof(block)); + copy_len = (len_metadata - offset) > 32 ? 32 : (len_metadata - offset); + memcpy(block, (uint8_t*)data_metadata + offset, copy_len); + + if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD, addr_metadata + offset, (uint32_t*)block) != HAL_OK){ + __BKPT(0); + } + offset += 32; + } + + SCB_InvalidateICache(); + SCB_InvalidateDCache(); + + HAL_FLASH_Lock(); + __enable_irq(); } static uint8_t is_valid_pc(uint32_t pc) { @@ -167,7 +184,7 @@ static uint8_t is_valid_pc(uint32_t pc) return (pc >= (uint32_t)&_stext && pc < (uint32_t)&_etext); } - +__attribute__((noreturn, optimize("O0"))) static void scan_call_stack(sContextStateFrame *frame, HardFaultLog *log_hard_fault) { uint32_t *stack_start = (uint32_t *)&_sstack; @@ -189,8 +206,6 @@ void my_fault_handler_c(sContextStateFrame *frame) { volatile uint32_t real_fault_pc = frame->return_address & ~1; volatile HardFaultLog log_hard_fault; - scan_call_stack(frame,&log_hard_fault); - volatile uint32_t *cfsr = (volatile uint32_t *)0xE000ED28; //keep the log in the estructure log_hard_fault.HF_flag = HF_FLAG_VALUE; @@ -235,15 +250,13 @@ void my_fault_handler_c(sContextStateFrame *frame) { const uint16_t INVSTATE = usage_fault & 0x0002; // Invalid processor state const uint16_t UNDEFINSTR = usage_fault & 0x0001; //Undefined instruction. } + if(usage_fault | bus_fault){ + scan_call_stack(frame,&log_hard_fault); + } volatile uint8_t metadata_buffer[0x100]; memcpy(metadata_buffer,(void*)METADATA_FLASH_ADDR,0x100); - flash_erase_hard_fault_sector(); //write log hard fault - volatile uint8_t hardfault_buffer[0x100]; - flash_write_blockwise(HF_FLASH_ADDR,(uint8_t*)&log_hard_fault,(sizeof(log_hard_fault) + 31)/32); - memcpy(hardfault_buffer,(void*)HF_FLASH_ADDR,0X200); - //write log Metadata_flash_addr - flash_write_blockwise(METADATA_FLASH_ADDR,metadata_buffer,(0x100)/32); + hardfault_flash_write(HF_FLASH_ADDR,(uint8_t*)&log_hard_fault,sizeof(log_hard_fault),METADATA_FLASH_ADDR,&metadata_buffer,sizeof(metadata_buffer)); //reboot the system volatile uint32_t *aircr = (volatile uint32_t *)0xE000ED0C; __asm volatile ("dsb"); diff --git a/STM32H723ZGTX_FLASH.ld b/STM32H723ZGTX_FLASH.ld index 9c4d227d..451e6934 100644 --- a/STM32H723ZGTX_FLASH.ld +++ b/STM32H723ZGTX_FLASH.ld @@ -52,7 +52,6 @@ MEMORY RAM_D3 (xrw) : ORIGIN = 0x38000000, LENGTH = 16K } -/* Define output sections */ SECTIONS { /* The startup code goes first into FLASH */ @@ -89,7 +88,18 @@ SECTIONS *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ . = ALIGN(4); } >FLASH - + /* =============================== + * Dedicated HardFault stack (DTCM) + * =============================== */ + .hardfault_stack (NOLOAD) : + { + . = ALIGN(8); + _hf_stack_start = .; + . += 0x400; /* 1 KB */ + _hf_stack_end = .; + } >DTCMRAM + +/* Define output sections */ .ARM.extab (READONLY): { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH .ARM (READONLY): { __exidx_start = .; diff --git a/STM32H723ZGTX_RAM.ld b/STM32H723ZGTX_RAM.ld index 56dab088..c661f7b4 100644 --- a/STM32H723ZGTX_RAM.ld +++ b/STM32H723ZGTX_RAM.ld @@ -152,6 +152,17 @@ SECTIONS __bss_end__ = _ebss; } >DTCMRAM + /* =============================== + * Dedicated HardFault stack (DTCM) + * =============================== */ + .hardfault_stack (NOLOAD) : + { + . = ALIGN(8); + _hf_stack_start = .; + . += 0x400; /* 1 KB */ + _hf_stack_end = .; + } >DTCMRAM + /* User_heap_stack section, used to check that there is enough RAM left */ ._user_heap_stack : { diff --git a/hard_faullt_analysis.py b/hard_faullt_analysis.py index 5b852019..35e6bfc9 100644 --- a/hard_faullt_analysis.py +++ b/hard_faullt_analysis.py @@ -8,18 +8,25 @@ CALL_TRACE_MAX_DEPTH = 16 def read_flash(): - cmd = [ - "STM32_Programmer_CLI", - "-c", "port=SWD", - "-r32", hex(HF_FLASH_ADDR), "112" - ] - out = subprocess.check_output(cmd, text=True) - return out - + try: + cmd = [ + "STM32_Programmer_CLI", + "-c", "port=SWD", + "-r32", hex(HF_FLASH_ADDR), "112" + ] + out = subprocess.check_output(cmd, text=True) + return out + except subprocess.CalledProcessError as e: + print("Stop debugging to check fault analysis!!!") + print(f"Error: {e}") + return None + except FileNotFoundError: + print("STM32_Programmer_CLI not found. Make sure it is installed and in PATH.") + return None def decode_cfsr_memory(cfsr, fault_addr): memory_fault = cfsr & 0xFF if memory_fault == 0: - return + return 0 print("\nMemory Fault (MMFSR):") if memory_fault & 0b10000000: print(f" MMARVALID: Memory fault address valid -> 0x{fault_addr:08X}") @@ -38,7 +45,7 @@ def decode_cfsr_memory(cfsr, fault_addr): print(" DACCVIOL : Data access violation (NULL pointer or invalid access)") if memory_fault & 0b00000001: print(" IACCVIOL : Instruction access violation") - + return 1 # -------------------------- # Decode Bus Fault (BFSR) @@ -46,20 +53,21 @@ def decode_cfsr_memory(cfsr, fault_addr): def decode_cfsr_bus(cfsr, fault_addr): bus_fault = (cfsr & 0x0000FF00) >> 8 if bus_fault == 0: - return + return 0 print("\nBus Fault (BFSR):") if bus_fault & 0b10000000: if(bus_fault & 0b00000001): print(f" BFARVALID : Bus fault address valid -> 0x{fault_addr:08X}") if bus_fault & 0b00000100: - print(f"\033[91m Bus fault address imprecise\033[0m") + print(f"\033[91m Bus fault address imprecise\033[0m (DON'T LOOK CALL STACK)") + if bus_fault & 0b00100000: print(" LSPERR : Floating Point Unit lazy state preservation error") if bus_fault & 0b00010000: print(" STKERR : Stack error on entry to exception") if bus_fault & 0b00001000: print(" UNSTKERR : Stack error on return from exception") - + return 2 # -------------------------- # Decode Usage Fault (UFSR) @@ -67,7 +75,7 @@ def decode_cfsr_bus(cfsr, fault_addr): def decode_cfsr_usage(cfsr): usage_fault = (cfsr & 0xFFFF0000) >> 16 if usage_fault == 0: - return + return 0 print("\nUsage Fault (UFSR):") if usage_fault & 0x0200: print(" DIVBYZERO : Division by zero") @@ -81,12 +89,14 @@ def decode_cfsr_usage(cfsr): print(" INVSTATE : Invalid processor state") if usage_fault & 0x0001: print(" UNDEFINSTR : Undefined instruction") - + return 4 def decode_cfsr(cfsr, fault_addr): - decode_cfsr_memory(cfsr, fault_addr) - decode_cfsr_bus(cfsr, fault_addr) - decode_cfsr_usage(cfsr) + error = 0 + error = decode_cfsr_memory(cfsr, fault_addr) + error + error = decode_cfsr_bus(cfsr, fault_addr) + error + error = decode_cfsr_usage(cfsr) + error + return error def addr2line(addr): @@ -96,11 +106,43 @@ def addr2line(addr): return output except Exception as e: return f"addr2line failed: {e}" + +def analyze_call_stack(calltrace_depth, calltrace_pcs, context=2): + """ + Muestra el call stack, omitiendo frames sin fuente y mostrando snippet de código. + """ + print("\n==== Call Stack Trace ====") + if calltrace_depth == 0: + print("No call trace available.") + return + +def analyze_call_stack(calltrace_depth, calltrace_pcs, context=0): + """ + Muestra el call stack, mostrando snippet de código de la línea exacta + sin intentar sumar líneas arriba/abajo (context=0 por defecto). + Omite frames sin fuente. + """ + print("\n==== Call Stack Trace ====") + if calltrace_depth == 0: + print("No call trace available.") + return + + for pc in calltrace_pcs[:calltrace_depth]: + pc_base = pc & ~1 + snippet = addr2line(pc_base- 4).strip() + if not snippet or snippet.startswith("??:?"): + continue # no hay fuente, saltar + print_code_context(snippet,1) + + print("======================================================") + + + def print_code_context(lines, context=2): """ - lines: salida de addr2line (función + file:line) - context: cuántas líneas arriba/abajo mostrar + lines: exit of addr2line (función + file:line) + context: how many lines up/down show """ line_list = lines.splitlines() if len(line_list) < 2: @@ -162,7 +204,7 @@ def hard_fault_analysis(memory_string): print(f" {r.upper():<4}: 0x{hf[r]:08X}") print(f" CFSR: 0x{hf['cfsr']:08X}") - decode_cfsr(hf["cfsr"], hf["fault_addr"]) + error = decode_cfsr(hf["cfsr"], hf["fault_addr"]) print("\nSource Location:") pc_loc = addr2line(hf["pc"]) lr_loc = addr2line(hf["lr"]) @@ -171,6 +213,7 @@ def hard_fault_analysis(memory_string): print(f" Program Counter : 0x{hf['pc']:08X} -> {pc_loc}") print_code_context(pc_loc) + analyze_call_stack(hf["calltrace_depth"],hf["calltrace_pcs"]) print("======================================================") @@ -184,6 +227,8 @@ def hard_fault_analysis(memory_string): if __name__ == '__main__': out = read_flash() + if(out == None): + exit() pos_memory_flash = out.rfind(HF_FLASH_ADDR_STRING) print(out[0:pos_memory_flash]) flash = out[pos_memory_flash:] From 224435cee01ca5c5b688d441c9e850bbc031f310 Mon Sep 17 00:00:00 2001 From: oganigl Date: Fri, 23 Jan 2026 17:54:37 +0100 Subject: [PATCH 13/18] change runes and some includes --- Core/Src/Runes/Runes.cpp | 1 - Core/Src/Runes/generated_metadata.cpp | 6 +++--- Core/Src/main.cpp | 23 ----------------------- Core/Src/stm32h7xx_it.c | 2 +- deps/ST-LIB | 2 +- 5 files changed, 5 insertions(+), 29 deletions(-) diff --git a/Core/Src/Runes/Runes.cpp b/Core/Src/Runes/Runes.cpp index 511a2cba..03aea7e3 100644 --- a/Core/Src/Runes/Runes.cpp +++ b/Core/Src/Runes/Runes.cpp @@ -41,7 +41,6 @@ FMAC_HandleTypeDef hfmac; * MPU ***********************************************/ -MPUManager::config MPUManager::MPUConfig = {}; /************************************************ * Communication-FDCAN diff --git a/Core/Src/Runes/generated_metadata.cpp b/Core/Src/Runes/generated_metadata.cpp index 94cda75d..e5ca657e 100644 --- a/Core/Src/Runes/generated_metadata.cpp +++ b/Core/Src/Runes/generated_metadata.cpp @@ -5,11 +5,11 @@ extern "C"{ const char DESCRIPTION[255] __attribute__((section(".metadata_pool")))= "****************" // placeholder for beggining - "20260120T161715" // DateTime using ISO-8601 format + "20260123T175359" // DateTime using ISO-8601 format " " // alignment - "6266c183" // STLIB commit + "814b9383" // STLIB commit "--------" // ADJ commit - "b202b1be" // Board commit + "22a8e607" // Board commit // the '=' is used for unparsing ; } \ No newline at end of file diff --git a/Core/Src/main.cpp b/Core/Src/main.cpp index 2cf182d8..db35498f 100644 --- a/Core/Src/main.cpp +++ b/Core/Src/main.cpp @@ -4,34 +4,11 @@ #include "stm32h7xx_hal.h" #include "core_cm7.h" - -void usage_fault_example(void) { - __builtin_trap(); -} -void func(){ - usage_fault_example(); -} -void f(){ - func(); -} -void a(){ - f(); -} -void busfault_example(void){ - *(uint32_t *)0xdead0000 = 0x20; -} -void memmanage_example(void) { - void (*fn_in_xn_region)(void) = (void (*)(void))0xE0000000; - fn_in_xn_region(); -} - int main(void) { #ifdef SIM_ON SharedMemory::start(); #endif Hard_fault_check(); - a(); - HAL_Init(); DigitalOutput led_on(PB0); STLIB::start(); Time::register_low_precision_alarm(100, [&]() { led_on.toggle(); diff --git a/Core/Src/stm32h7xx_it.c b/Core/Src/stm32h7xx_it.c index e2b8f7a5..4b59c329 100644 --- a/Core/Src/stm32h7xx_it.c +++ b/Core/Src/stm32h7xx_it.c @@ -21,7 +21,7 @@ #include "main.h" #include "stm32h7xx_it.h" #include "stm32h7xx_hal.h" -#include "HALAL/Benchmarking_toolkit/HardfaultTrace.h" +#include "HALAL/HardFault/HardfaultTrace.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ /* USER CODE END Includes */ diff --git a/deps/ST-LIB b/deps/ST-LIB index 332e04d7..814b9383 160000 --- a/deps/ST-LIB +++ b/deps/ST-LIB @@ -1 +1 @@ -Subproject commit 332e04d7b84d18e36df36a9e7366c03d030b3a02 +Subproject commit 814b93836c9cbc481281c072f6aaafb0899ccd66 From 381678dcaffaf5559d6f083f70c1d337a1532e33 Mon Sep 17 00:00:00 2001 From: oganigl Date: Fri, 23 Jan 2026 18:10:16 +0100 Subject: [PATCH 14/18] change stlib deps --- deps/ST-LIB | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/ST-LIB b/deps/ST-LIB index 814b9383..7f4d9089 160000 --- a/deps/ST-LIB +++ b/deps/ST-LIB @@ -1 +1 @@ -Subproject commit 814b93836c9cbc481281c072f6aaafb0899ccd66 +Subproject commit 7f4d908944249b3723c248ea6dc79a2a3527ba84 From bcb5f629de381b5f9f02e7a6c10234af27397c9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=93scar=20Gand=C3=ADa=20Iglesias?= <145703854+oganigl@users.noreply.github.com> Date: Fri, 23 Jan 2026 19:53:23 +0100 Subject: [PATCH 15/18] some more changes to avoid errors --- .vscode/settings.json | 3 +-- Core/Inc/main.h | 1 + Core/Src/main.cpp | 3 +-- tools/retrieve_flash_data.py | 4 ++-- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 66a250fa..019c2c08 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -24,6 +24,5 @@ "mutex": "cpp", "shared_mutex": "cpp", "regex": "cpp" - }, - "cortex-debug.variableUseNaturalFormat": false + } } diff --git a/Core/Inc/main.h b/Core/Inc/main.h index 0a0d29d8..e8512dba 100644 --- a/Core/Inc/main.h +++ b/Core/Inc/main.h @@ -146,6 +146,7 @@ void Error_Handler(void); /* USER CODE BEGIN Private defines */ /* USER CODE END Private defines */ + #ifdef __cplusplus } #endif diff --git a/Core/Src/main.cpp b/Core/Src/main.cpp index db35498f..e2e14f6a 100644 --- a/Core/Src/main.cpp +++ b/Core/Src/main.cpp @@ -1,8 +1,6 @@ #include "main.h" #include "ST-LIB.hpp" -#include "stm32h7xx_hal.h" -#include "core_cm7.h" int main(void) { #ifdef SIM_ON @@ -11,6 +9,7 @@ int main(void) { Hard_fault_check(); DigitalOutput led_on(PB0); STLIB::start(); + Time::register_low_precision_alarm(100, [&]() { led_on.toggle(); }); diff --git a/tools/retrieve_flash_data.py b/tools/retrieve_flash_data.py index 9d9dbf3c..1ebf07d9 100644 --- a/tools/retrieve_flash_data.py +++ b/tools/retrieve_flash_data.py @@ -23,8 +23,8 @@ def main(): exit(-1) binary_raw = None - with open("dump.bin","rb") as binary: - + + with open("dump.bin","r") as binary: binary_raw = binary.read() #DEFINITIONS FOR LOCATIONS From 7fc2c213c798f1bb49400d9a677cf5517060b67c Mon Sep 17 00:00:00 2001 From: oganigl Date: Fri, 23 Jan 2026 21:40:42 +0100 Subject: [PATCH 16/18] add new deps/stlib again --- Core/Src/Runes/generated_metadata.cpp | 6 +++--- deps/ST-LIB | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Core/Src/Runes/generated_metadata.cpp b/Core/Src/Runes/generated_metadata.cpp index e5ca657e..75181f29 100644 --- a/Core/Src/Runes/generated_metadata.cpp +++ b/Core/Src/Runes/generated_metadata.cpp @@ -5,11 +5,11 @@ extern "C"{ const char DESCRIPTION[255] __attribute__((section(".metadata_pool")))= "****************" // placeholder for beggining - "20260123T175359" // DateTime using ISO-8601 format + "20260123T214025" // DateTime using ISO-8601 format " " // alignment - "814b9383" // STLIB commit + "e2a56178" // STLIB commit "--------" // ADJ commit - "22a8e607" // Board commit + "1b75e823" // Board commit // the '=' is used for unparsing ; } \ No newline at end of file diff --git a/deps/ST-LIB b/deps/ST-LIB index 7f4d9089..e2a56178 160000 --- a/deps/ST-LIB +++ b/deps/ST-LIB @@ -1 +1 @@ -Subproject commit 7f4d908944249b3723c248ea6dc79a2a3527ba84 +Subproject commit e2a56178a9ed2cebb53a4840e00f862e5b9e3935 From b71f934b1a6088410d2698c3a8b08f3ac9b6f7d2 Mon Sep 17 00:00:00 2001 From: oganigl Date: Tue, 27 Jan 2026 12:26:02 +0100 Subject: [PATCH 17/18] added Examples and make sure that works with the MPUmanager --- Core/Src/Examples/ExamplesHardFault.cpp | 58 +++++++++++++++++++++++++ Core/Src/main.cpp | 29 ++++--------- 2 files changed, 67 insertions(+), 20 deletions(-) create mode 100644 Core/Src/Examples/ExamplesHardFault.cpp diff --git a/Core/Src/Examples/ExamplesHardFault.cpp b/Core/Src/Examples/ExamplesHardFault.cpp new file mode 100644 index 00000000..f569b5c0 --- /dev/null +++ b/Core/Src/Examples/ExamplesHardFault.cpp @@ -0,0 +1,58 @@ +#ifdef EXAMPLE_HARDFAULT + +#include "main.h" +#include "ST-LIB.hpp" + +#ifdef TEST_MEMORY_FAULT +constexpr auto my_uint32_t = MPUDomain::Buffer(); + +int main(void) { + + Hard_fault_check(); + STLIB::start(); + + using myBoard = ST_LIB::Board; + myBoard::init(); + + [[maybe_unused]] auto my_buffer = myBoard::instance_of().template as(); + my_buffer[1000000000] = 5; + while (1) { + STLIB::update(); + } +} + +#endif + +#ifdef TEST_BUS_FAULT + +int main(void) { + Hard_fault_check(); + *(uint32_t*)0xdead0000 = 0x20; + STLIB::start(); + + using myBoard = ST_LIB::Board<>; + myBoard::init(); + + while (1) { + STLIB::update(); + } +} + +#endif + +#ifdef TEST_USAGE_FAULT + +int main(void) { + Hard_fault_check(); + __builtin_trap(); + STLIB::start(); + using myBoard = ST_LIB::Board<>; + myBoard::init(); + + while (1) { + STLIB::update(); + } +} + +#endif +#endif \ No newline at end of file diff --git a/Core/Src/main.cpp b/Core/Src/main.cpp index fd63fc26..c367556e 100644 --- a/Core/Src/main.cpp +++ b/Core/Src/main.cpp @@ -1,34 +1,23 @@ -#define EXAMPLE_BASE -#define TEST_0 // Test to be run - -// Include all examples, run the one defined above #include "Examples/ExampleMPU.cpp" - -#ifdef EXAMPLE_BASE +#include "Examples/ExamplesHardFault.cpp" #include "main.h" #include "ST-LIB.hpp" -int main(void) { -#ifdef SIM_ON - SharedMemory::start(); -#endif - Hard_fault_check(); - DigitalOutput led_on(PB0); - STLIB::start(); +int main(void) { + Hard_fault_check(); + STLIB::start(); - Time::register_low_precision_alarm(100, [&]() { led_on.toggle(); - }); + using myBoard = ST_LIB::Board<>; + myBoard::init(); - while (1) { - STLIB::update(); - } + while (1) { + STLIB::update(); + } } - void Error_Handler(void) { ErrorHandler("HAL error handler triggered"); while (1) { } } -#endif From 27d1d38c42389f2fd1b7cbd82ebd720d09d18ff5 Mon Sep 17 00:00:00 2001 From: oganigl Date: Tue, 27 Jan 2026 17:52:21 +0100 Subject: [PATCH 18/18] change the asm name instruction --- Core/Src/stm32h7xx_it.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/Src/stm32h7xx_it.c b/Core/Src/stm32h7xx_it.c index 4b59c329..2a1d6d41 100644 --- a/Core/Src/stm32h7xx_it.c +++ b/Core/Src/stm32h7xx_it.c @@ -97,7 +97,7 @@ extern uint32_t _hf_stack_end; //calls my_fault_handler with the MSP(main stack pointer) #define HARDFAULT_HANDLING_ASM() \ -__asm volatile( \ +__asm__ __volatile__( \ /* Detect which stack was in use */ \ "tst lr, #4 \n" \ "ite eq \n" \