cancel
Showing results for 
Search instead for 
Did you mean: 

[STM32H7] Flash write returns OK, yet hard fault during read-back

bnguy.1
Associate III

I have an STM32H7, and despite a HAL_OK for every write,

	HAL_FLASH_Unlock();
	if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD, 0x081E0000+ (32*fw), (uint32_t)(pBuffer)) != HAL_OK)
	{
             Error_Handler();
	}
	HAL_FLASH_Lock();
 
 
 

OCCASIONALLY, the write appears to cause an alignment/ECC error. Simply READING from the sector after writing, will cause a Hard-Fault/IRQ0. The only way to recover, is to use the bootloader to erase.

For testing, I'm writing an incrementing pattern, and the fault seems to happen randomly at a different address/data each time.

The source buffer is in it a section of memory that has dma buffers, not sure if that could be causing a problem. Is there a way to find what exactly is the cause and/or a way to disable the ECC (if it's due to an alignment issue) and/or CACHE?

5 REPLIES 5
Pavel A.
Evangelist III

IIRC this looks like effect of either D or I cache,

Try to disable all caches and see if the problem reproduces.

(assuming you're using the latest Cube library v 1.8 or your own code)

Note that you can prevent jumping to exception handler (ignore the exception) and check for errors later.

-- pa

bnguy.1
Associate III

I'm running the latest cube with the cache disabled in HAL.. i.e. in main, there's no:

  SCB_EnableICache();
  SCB_EnableDCache();

How do you prevent jumping to the HardFault/IRQ0? It happens even if I use the debugger Memory window to view the flash memory.

You should enable separate handling of specific exceptions to prevent their automatic elevation to hardfault.

Example below shows how to do this for BUSFAULT (usually caused by internal flash controller errors)

void flash_unlock_test()
{
    uint32_t vSHCSR = SCB->SHCSR;
    // enable separate BUSFAULT exception:
    vSHCSR |= SCB_SHCSR_BUSFAULTENA_Msk;
    SCB->SHCSR = vSHCSR;
    vSHCSR = SCB->SHCSR; // read back
 
    __disable_fault_irq();
    __DSB();
    
    // >>>> Do something here that can raise BUSFAULT
 
    vSHCSR = SCB->SHCSR;
   if  ( vSHCSR & SCB_SHCSR_BUSFAULTPENDED_Msk) {
     printf("Busfault!\n");
   }
 
    //CLEAR the BUSFAULT
    vSHCSR &= ~SCB_SHCSR_BUSFAULTPENDED_Msk;
    SCB->SHCSR = vSHCSR;
    __DSB();
 
    __enable_fault_irq();
}

TUT.1
Associate II

Hello,

same issue. Did you find a solution?