2020-10-12 11:04 PM
I use STM32L431, it only possible to program double word, I want program a new data to FLASH if the 64 bits all is '1' in FLASH, otherwise, if the 64 bits is not all '1', I erase it first before program. But when I program a 0xffffffffffffffff to the 64 bits and then need to program a new data(for example: 0x1122334455667788), it fail to program.
void Flash_Test(void)
{
uint32_t startAddr = 0x0801C000;
HAL_StatusTypeDef status;
FLASH_EraseInitTypeDef EraseInitStruct;
uint32_t pageErr;
printf("erase one page\r\n");
/*erase one page*/
HAL_FLASH_Unlock();
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPTVERR);
EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
EraseInitStruct.Banks = GetBank(startAddr);
EraseInitStruct.Page = GetPage(startAddr);
EraseInitStruct.NbPages = 1;
status = HAL_FLASHEx_Erase(&EraseInitStruct, &pageErr);
HAL_FLASH_Lock();
if (status != HAL_OK)
return;
printf("before write 0xff to one page\r\n");
for (int i = 0; i < 2048; i += 4)
{
printf("%x ", *(volatile uint32_t*)(startAddr + i));
}
printf("\r\n");
/*write 0xff to one page*/
HAL_FLASH_Unlock();
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPTVERR);
for (int i = 0; i < 2048; i += 8)
{
status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, startAddr + i, 0xffffffffffffffff);
if (status != HAL_OK)
{
printf("Fail to write all pages!\r\n");
break;
}
}
HAL_FLASH_Lock();
printf("after write 0xff to one page\r\n");
for (int i = 0; i < 2048; i += 4)
{
printf("%x ", *(volatile uint32_t*)(startAddr + i));
}
printf("\r\n");
printf("write 0xff\r\n");
/*write 8 bytes*/
HAL_FLASH_Unlock();
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPTVERR);
status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, startAddr, 0xffffffffffffffff);
if (status != HAL_OK)
{
printf("Fail to write 8 bytes!\r\n");
}
HAL_FLASH_Lock();
}
Run this sample code, it will print "Fail to write 8 bytes".
Possible to program 1 to 0 and can't program 0 to 1 is FLASH's feature. In this case, even if all the bits is '1' in FLASH, HAL_FLASH_Program still return HAL_ERROR. Why?
Thanks!
Solved! Go to Solution.
2020-10-13 08:00 AM
Zzhou.2:
waclawek.jan's comment regarding the "hidden ECC bits getting programmed with a non-FF value" did not mean to imply that they were programmed incorrectly; indeed, the value programmed is correct -- that is, reading back the 0xFFFFFFFF will not result in a double-bit error (ECCD flag). What it means when the ECC bits are programmed to a non-FF value is that the corresponding STM32 Flash location is no longer alterable. In other words, when the device is erased, each 64-bits of Flash data and the associated 8 ECC bits all contain ''1' . This represents something of an "impossible" condition, since the ECC bits for a 64-bit value of "all FFs" is NOT itself 0xFF. You can perhaps understand this as being a specific condition rather than just one of many value settings. In any case, each of these '1's can be programmed to a '0' using the Flash write procedure, but any '0's cannot be programmed back to '1' -- they can only be erased to achieve that change. So, if you take a double-word Flash location that already contains 64 bits of '1's and perform a Flash write of (0xFFFFFFFF, 0xFFFFFFFF), it results in the same value but a different condition: that is, the 8 ECC bits will have changed. And once you've changed those, you cannot change them back. So, the writing of even a (0xFFFFFFFF,0xFFFFFFFF) will result in some '0' bits (in the corresponding ECC location), which will prevent you from being able to re-write that location. So, the error you should be getting when you try is not ECCD, but rather simply that the location could not be re-written.
2020-10-13 12:20 AM
The 'L4 FLASH has ECC. When you program 0xFFFFFFFFFFFFFFFF, the hidden ECC byte gets programmed to a non-FF value, this prevents further programming.
JW
2020-10-13 01:30 AM
But the variable pFlash.ErrorCode=0xa8 in function FLASH_WaitForLastOperation,not detect the flag FLASH_FLAG_ECCD.
2020-10-13 02:17 AM
I don't know what are those values you mention, I don't use Cube. You may want to talk in terms of register flags as given by the Reference Manual.
I suspect the dedicated ECCD error occurs only when you *read* from a FLASH position with mismatched ECC.
JW
2020-10-13 08:00 AM
Zzhou.2:
waclawek.jan's comment regarding the "hidden ECC bits getting programmed with a non-FF value" did not mean to imply that they were programmed incorrectly; indeed, the value programmed is correct -- that is, reading back the 0xFFFFFFFF will not result in a double-bit error (ECCD flag). What it means when the ECC bits are programmed to a non-FF value is that the corresponding STM32 Flash location is no longer alterable. In other words, when the device is erased, each 64-bits of Flash data and the associated 8 ECC bits all contain ''1' . This represents something of an "impossible" condition, since the ECC bits for a 64-bit value of "all FFs" is NOT itself 0xFF. You can perhaps understand this as being a specific condition rather than just one of many value settings. In any case, each of these '1's can be programmed to a '0' using the Flash write procedure, but any '0's cannot be programmed back to '1' -- they can only be erased to achieve that change. So, if you take a double-word Flash location that already contains 64 bits of '1's and perform a Flash write of (0xFFFFFFFF, 0xFFFFFFFF), it results in the same value but a different condition: that is, the 8 ECC bits will have changed. And once you've changed those, you cannot change them back. So, the writing of even a (0xFFFFFFFF,0xFFFFFFFF) will result in some '0' bits (in the corresponding ECC location), which will prevent you from being able to re-write that location. So, the error you should be getting when you try is not ECCD, but rather simply that the location could not be re-written.
2020-10-13 08:08 AM
You get to program the cells ONCE, for the 0xFFFFFFFFF, 0xFFFFFFFFF case opt not to write them the first time around
2020-10-15 03:22 PM
2020-10-15 03:22 PM
@GCord.1 thanks for the exhaustive explanation.
Jan