cancel
Showing results for 
Search instead for 
Did you mean: 

Flash that goes into "Inconsistency error" during second word write in debug mode, and first write is 0 in normal run.

Thomas Gonnot
Associate II

Hello

I'm working on the implementation of a UF2 bootloader for the STM32H743ZI, and I get an issue with the flash that goes into "Inconsistency error" during second word write.

I have properly erased the flash sector before the write.

Here is the function to write the flash:

uint8_t erased_sectors[MCU_FLASH_SIZE / FLASH_SECTOR_SIZE];
uint8_t written_blocks[NUMBER_FLASH_BLOCKS / 8];
 
int flash_write(uint32_t addr, void const *data, uint32_t len)
{
 HAL_StatusTypeDef status = HAL_OK;
 uint32_t offset = addr - FLASH_APP_START;
 uint32_t bank = 0;
 switch(offset / MCU_FLASH_BANK_SIZE)
 {
  case 0:
   bank = FLASH_BANK_1;
   break;
  case 1:
   bank = FLASH_BANK_2;
   break;
 }
 // Data must be aligned on blocks of 256 bits
 if(offset % (FLASH_PROG_SIZE * 4) != 0)
	 return -1;
 // Check if the block was already written
 uint32_t blockNumber = offset / UF2_BLOCK_SIZE;
 uint32_t blockIndex = blockNumber / 8;
 uint8_t blockPosition = blockNumber % 8;
 if(written_blocks[blockIndex] & (1 << blockPosition))
  return len;
 // Checks Flash status
 status = FLASH_WaitForLastOperation(10, bank);
 if(status == HAL_TIMEOUT)
  return 0;
 if(status == HAL_ERROR)
  return -1;
 // Unlocks the flash
 if(HAL_FLASH_Unlock() != HAL_OK)
  return -1;
 // Check if the sector was previously erased
 uint32_t sectorIndex = offset / FLASH_SECTOR_SIZE;
 uint32_t sectorIndexInBank = sectorIndex % FLASH_SECTOR_TOTAL;
 if(erased_sectors[sectorIndex] == 0)
 {
  // Erase sector
	FLASH_Erase_Sector(sectorIndexInBank, bank, FLASH_VOLTAGE_RANGE_1);
  erased_sectors[sectorIndex]++;
	status = FLASH_WaitForLastOperation(10, bank);
	if(status == HAL_TIMEOUT)
	{
	 HAL_FLASH_Lock();
	 return 0;
	}
  if(status == HAL_ERROR)
  {
   HAL_FLASH_Lock();
   return -1;
  }
 }
 for(uint32_t i = 0; i < len; i += FLASH_PROG_SIZE)
 {
	status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD, addr + i, ((uint32_t)data) + i);
	if(status == HAL_ERROR)
   return -1;
 }
 HAL_FLASH_Lock();
 written_blocks[blockIndex] |= 1 << blockPosition;
 return len;
}

MCU_FLASH_SIZE = 2*1024*1024

FLASH_SECTOR_SIZE = 0x00020000 (defined in HAL)

FLASH_SECTOR_TOTAL = 8 (defined in HAL)

UF2_BLOCK_SIZE = 256

NUMBER_FLASH_BLOCKS = MCU_FLASH_SIZE / UF2_BLOCK_SIZE

FLASH_APP_START = 0x08000000

FLASH_PROG_SIZE = FLASH_NB_32BITWORD_IN_FLASHWORD = 8

Now in the main, I have the following code:

int main(void)
{
  // Initialization
  // ....
  // ....
  memset(erased_sectors, 0, sizeof(erased_sectors));
  memset(written_blocks, 0, sizeof(written_blocks));
 
  uint8_t data[256] = "This is a test of programming of the STM32H743ZI flash memory.";
 
  flash_write(0x08100000, data, 256);
  flash_write(0x08100000 + 256, data, 256);
  while(1);
}

When debugging step by step, the program manages to write the first 32 bytes of the data, but on the second set of 32 bytes, the 7th 32bits write fails with the "Inconsistency error" flag set, followed of course by the "Programming sequence error" on the next write.

When running free however, after checking the flash content, I only get a block of 32 bytes filled with zeros per call of my function.

Anybody has an indea what is happening, what I am doing wrong here?

I'm working with the STM32Cube FW_H7 V1.9.1 and the CubeIDE.

Thank you

2 REPLIES 2
TDK
Guru

> STM32H743ZI

> int flash_write(uint32_t addr, void const *data, uint32_t len)

> status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD, addr + i, ((uint32_t)data) + i);

You convert a pointer to void to an integer, then add a value to it, which is nonsense.

data should be of type (uint8_t *) or similar.

You're also writing words to non-word aligned addresses, which I'm not sure is allowed, especially if the bytes span a flash page. But writing to the same byte 4x definitely isn't allowed and will lead to ECC issues.

Write consecutive words instead and you shouldn't have issues.

If you feel a post has answered your question, please click "Accept as Solution".
Thomas Gonnot
Associate II

Fair enough on the cast, I could just keep it as a void *.

The real issue is that I forgot that the FLASH_PROG_SIZE was in 32bits words, not 8 bits, so it was a simple fix:

for(uint32_t i = 0; i < len; i += FLASH_PROG_SIZE * 4)

Now it works well in debug mode if I go step by step.

However, when I run the program without going step by step, it doesn't seem to be writting anything...

Any idea what that would be about?