cancel
Showing results for 
Search instead for 
Did you mean: 

HAL_FLASHEx_Erase and HAL_FLASH_Program both return HAL_ERROR but erase and write are done.

CHage.1
Associate

These problems are probably related. I'm running STM32G473 at 160 MHz. I'm attempting to erase one page followed by 34 double-word writes to the same page. The code and the target are both in bank 1, but the problem occurs if I move the target to bank 2.

The HAL_FLASHEx_Erase eventually calls FLASH_PageErase. The working lines of FLASH_PageErase are

  MODIFY_REG(FLASH->CR, FLASH_CR_PNB, ((Page & 0xFFU) << FLASH_CR_PNB_Pos));
  SET_BIT(FLASH->CR, FLASH_CR_PER);
  SET_BIT(FLASH->CR, FLASH_CR_STRT);

I believe the proper sequence is that setting the STRT bit starts the erase and sets the BUSY bit in SR. When the erase is finished, the BUSY bit should be cleared. Following the FLASH_PageErase is call to FLASH_WaitForLastOperation, which spins waiting for BUSY to clear and then looks at the SR.

In my case the flash page is erased, but PGSERRis set in SR. I don't know why PGSERR is set: DBANK == 1 and SR == 0 before the erase sequence.

The behavior changes if I debug and install breakpoints. I modified the code to capture SR before and after setting STRT

  MODIFY_REG(FLASH->CR, FLASH_CR_PNB, ((Page & 0xFFU) << FLASH_CR_PNB_Pos));
  SET_BIT(FLASH->CR, FLASH_CR_PER);
  sr_log[0] = FLASH->SR;
  SET_BIT(FLASH->CR, FLASH_CR_STRT);
  sr_log[1] = FLASH->SR;
  sr_log[2] = FLASH->SR;
  sr_log[3] = FLASH->SR;
  sr_log[4] = FLASH->SR;
  sr_log[5] = FLASH->SR;

If I break after the write to sr_log[5] (that is, let it run freely, sr_log[0] = 0, sr_log[1]= BUSY, sr_log[2] = PGSERR

If I break at sr_log[1] = FLASH->SR, that is immediately after setting STRT, then continue, all sr_log entries are 0. Apparently when the breakpoint is hit, the flash operation completes, and we execution continues SR BUSY has already cleared AND PGSERR does not set. FLASH_WaitForLastOperation returns HAL_OK, as you would expect.

Okay, there is some timing issue, but what? I've tried disabling both caches and interrupts with no difference.

The write operations fail with similar but different symptoms. In all cases the data is written correctly, but sometimes PGSERR and PROGERR are set. (PROGERR would indicate trying to write to unerased flash, but I check for 0xfff... before the write, and I've also tried writing 0x0, which should work even if the flash in not erased. Seventeen writes are performed in a loop. Most of the writes return HAL_OKAY, but some return HAL_ERROR. There is no pattern to the failures that I can see. For example, in one trial, loop 4, 6, 12 fail. In another it could be 0, 5, 14, 24.

I'm not doing anything exotic, so I think I must be overlooking something very basic, but I sure don't know what. Anyone have suggestions that I haven't tried?

0 REPLIES 0