STM32 gotchas
136. Cannot reprogram FLASH (after inadvertent write access to FLASH area, and if Cube/HAL is used)

In a fairly complex piece of software, due to a bug, a pointer variable was zeroed inadvertently. This pointer normally serves to access a struct in RAM, so after this event, inadvertent writes started to occur to low addresses, just above 0x0000'0000. It means, processor attempted to write into FLASH, which was mapped to this area as it is by default. These writes of course did not modify the content of FLASH, as these were plain writes, no proper FLASH-write sequences.

Upon these writes, the FLASH controller set FLASH_SR.PGSERR, as it considered these to be FLASH-write-sequencing errors - exactly as documented, since FLASH_CR.PG/FSTPG had not been set previously. Depending on particular write width and address, FLASH_SR.SIZERR and FLASH_SR.PGAERR were set, too.

In other parts of the program, data were to be written into FLASH. For this, Cube/HAL functions were used: HAL_FLASHEx_Erase() and HAL_FLASH_Program(). These both call FLASH_WaitForLastOperation() as the very first thing, and don't proceed if it does not return HAL_OK. FLASH_WaitForLastOperation() is there to wait for any outstanding FLASH operation from previous run, so it loops with a timeout waiting for FLASH_SR.BSY to clear. But then, for good measure, it also checks wheter some of the programming-failure-indicating flags in FLASH_SR is not set - and since they were set, it returned HAL_ERROR.

The net effect was, that "legitimate" writes to FLASH stopped to work.

This issue has been observed on STM32L431. Other models/families may behave differently.