STM32H7 Hard Fault
I have a program where data is read into the dataStore buffer of a double buffered system from external flash memory via SPI upon detection of an interrupt, around every 700ms; the only ISR sets a value and if the block in my main loop detects this value then it resets the value and processes the block. During processing, it sets up a queue to read new data into the opposing buffer to be undertaken at an appropriate time after completion of the current processing and it all starts again.
There is plenty of time between updates and varying the speed of the flash (between 7.5 and 60 MHz) can either make it worse or better; irrespective of this, the actual read via SPI can range from about <100us to 5ms, depending on the speed that the interface is configured to. At 7.5 MHz, it trips over frequently, at 60 MHz it is relatively stable. I know the obvious run it at 60 MHz then, but I need to get to the bottom of this instability issue.
The Fault Analyzer of STM32CubeIDE is indicating a Hard Fault from Bus, memory or usage fault (FORCED). The Bus Fault Details indicate Imprecise data access violation (IMPRECISERR). The Register Content During Fault Exception has the PC pointing at the following line:
myData = dataStore[ buff[object] ][object][position];The variables in this line were previously defined as:
uint32_t dataStore[2][16][128];
uint32_t object;
uint32_t buff[16];
uint32_t position;
uint32_t myData;and these variables have the following state upon error:
object == 0
buff[0] == 0
position == 6
dataStore[0][0][] == { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ..., 126, 127 };
myData == 5So far so good, accessing the data within dataStore appears to have triggered the fault somehow as the new value hasn't yet been transferred to the myData variable. The question is how has this happened?
Unfortunately, I don't have a JTAG interface on the custom board (only SWD), nor do I have an external debugger, except an external ST-Link V2 device to connect to the SWD. However, I have managed to get some information from the HardFault Analyzer of the STM32CCubeProgrammer:
13:17:47:533 : -------------------------------------------------------------------
13:17:47:535 : STM32CubeProgrammer HardFault Analyzer
13:17:47:536 : -------------------------------------------------------------------
13:17:47:536 : halt ap 0
13:17:47:542 : Execution Mode : Handler
13:17:47:542 : r ap 0 @0x2407FEE8 0x00000020 bytes
13:17:47:542 : r ap 0 @0xE000ED2A 0x00000002 bytes
13:17:47:542 : No Usage Fault detected
13:17:47:542 : r ap 0 @0xE000ED29 0x00000001 bytes
13:17:47:543 : Bus Fault detected in instruction located at 0x08001B44
13:17:47:579 : IMPRECISERR : a data bus error has occurred but the return address
13:17:47:580 : in the stack frame is not related to the instruction that caused the error.
13:17:47:580 : r ap 0 @0xE000ED28 0x00000001 bytes
13:17:47:580 : No MemManage Fault detected
13:17:47:580 : HardFault detected :
13:17:47:628 : Faulty function called at this location 0x080017D1
13:17:47:628 : r ap 0 @0xE000ED2C 0x00000004 bytes
13:17:47:629 : HardFault State Register information :
13:17:47:629 : FORCED : forced HardFault.
13:17:47:629 : Exception return information :
13:17:47:630 : Return to Thread mode, exception return uses non-floating-point
13:17:47:630 : state from MSP and execution uses MSP after return.
This again points to the 'rogue' instruction identified above - for some reason.
Of further relevance, all variables in question have been defined within the same D1 memory domain as the rest of the program and I'm not using the cache at all. Both minimum stack and heap size were initially increased to 0x2000 and then 0x10000. The hardware is a custom board with the STM32H750 and also have experienced this with the Nucleo H743ZI2 boards, the latter I had put the problem down to noise owing to the leads required to connect the external flash memory.
