Sector Erasing in STM32--chip crashes on 256kB erase
I am working on erasing sectors sequentially in my MCU, from Sector 2 through Sector 7 (the size of flash where my firmware will live). I have found that sequential sector erases will occasionally fail, and any attempt to erase a sector of size 256kB will crash the MCU.
My chip is fed 1.8V steady, so it is in the HAL VOLTAGE_RANGE_1, erasing bytes. My code is below, with the HAL function for sector erasing directly out of the zip file. Am I missing something at a software level? Or is it related to the 1.8V level. Erasing a sector of 256 kB should be possible with that voltage level correct? Also happy to clarify if need be.
uint8_t Bootloader_Erase(void)
{
HAL_StatusTypeDef FlashStatus = HAL_OK;
HAL_FLASH_Unlock();
FLASH_EraseInitTypeDef pEraseInit;
pEraseInit.TypeErase = TYPEERASE_SECTORS;
pEraseInit.Sector = 5;
pEraseInit.NbSectors = 1;
pEraseInit.VoltageRange = FLASH_VOLTAGE_RANGE_1;
FlashStatus = HAL_FLASHEx_Erase(&pEraseInit, &SectorError);
HAL_FLASH_Lock();
if (FlashStatus != HAL_OK)
{
return 0;
}
else {return 1;}
}
HAL_StatusTypeDef HAL_FLASHEx_Erase(FLASH_EraseInitTypeDef *pEraseInit, uint32_t *SectorError)
{
HAL_StatusTypeDef status = HAL_ERROR;
uint32_t index = 0;
/* Process Locked */
__HAL_LOCK(&pFlash);
/* Check the parameters */
// assert_param(IS_FLASH_TYPEERASE(pEraseInit->TypeErase));
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
if(status == HAL_OK)
{
/*Initialization of SectorError variable*/
*SectorError = 0xFFFFFFFFU;
/* Check the parameters */
// assert_param(IS_FLASH_NBSECTORS(pEraseInit->NbSectors + pEraseInit->Sector));
/* Erase by sector by sector to be done*/
for(index = pEraseInit->Sector; index < (pEraseInit->NbSectors + pEraseInit->Sector); index++)
{
FLASH_Erase_Sector(index, (uint8_t) pEraseInit->VoltageRange);
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
/* If the erase operation is completed, disable the SER Bit and SNB Bits */
CLEAR_BIT(FLASH->CR, (FLASH_CR_SER | FLASH_CR_SNB));
if(status != HAL_OK)
{
/* In case of error, stop erase procedure and return the faulty sector*/
*SectorError = index;
break;
}
}
}
/* Process Unlocked */
__HAL_UNLOCK(&pFlash);
return status;
}
HAL_StatusTypeDef FLASH_Erase_Sector(uint32_t Sector, uint8_t VoltageRange)
{
uint32_t tmp_psize = 0;
if(VoltageRange == FLASH_VOLTAGE_RANGE_1)
{
tmp_psize = FLASH_PSIZE_BYTE;
}
else if(VoltageRange == FLASH_VOLTAGE_RANGE_2)
{
tmp_psize = FLASH_PSIZE_HALF_WORD;
}
else if(VoltageRange == FLASH_VOLTAGE_RANGE_3)
{
tmp_psize = FLASH_PSIZE_WORD;
}
else
{
tmp_psize = FLASH_PSIZE_DOUBLE_WORD;
}
/* If the previous operation is completed, proceed to erase the sector */
FLASH->CR &= CR_PSIZE_MASK;
FLASH->CR |= tmp_psize;
FLASH->CR &= SECTOR_MASK;
FLASH->CR |= FLASH_CR_SER | (Sector << POSITION_VAL(FLASH_CR_SNB));
FLASH->CR |= FLASH_CR_STRT;
/* Data synchronous Barrier (DSB) Just after the write operation
This will force the CPU to respect the sequence of instruction (no optimization).*/
__DSB();
}