cancel
Showing results for 
Search instead for 
Did you mean: 

ECCD problems when reading back a flash location programmed with HAL FLASH API

CTabo.1
Senior

Hello,
I am developing a RAM-based bootloader on STM32H5, to update my firmware application.

Application and bootloader resides on different flash areas, and the bootloader code is copied into RAM at startup.

[0x8000000 - 0x801FFFF] bootloader
[0x8020000 - 0x803FFFF] reserved
[0x8040000 - 0x80FFFFF] application

 

First, the bootloader erases all the application sectors.
Then the bootloader receives code fragments via fieldbus, and program the flash memory 16 bytes (flash-word) at time, at correctly aligned addresses:

int16_t HW_FLASH_Program(uint32_t addr, int32_t len, uint8_t *buff_p)
{
	HAL_StatusTypeDef 	status;
	uint8_t 			flash_word[FLASH_WORD_LEN];
	uint32_t 			aligned_addr;
	uint32_t 			offset;
	uint32_t 			chunk;

	HAL_FLASH_Unlock();

	while (len > 0)
	{
		// back-align the address to 16 bytes
		aligned_addr = addr & ~(FLASH_WORD_LEN - 1);

		if ((addr == aligned_addr) && (len >= FLASH_WORD_LEN))
		{
			status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_QUADWORD, addr, (uint32_t)buff_p);

			LL_ICACHE_Invalidate();

			if (status != HAL_OK)
			{
				HAL_FLASH_Lock();
				return -1;
			}

			addr += FLASH_WORD_LEN;
			buff_p += FLASH_WORD_LEN;
			len -= FLASH_WORD_LEN;
		}
		else
		{
			// address not aligned or length less than 16 bytes

			// read the current contents of the flash word
			for (uint32_t i = 0; i < FLASH_WORD_LEN; i++)
			{
				flash_word[i] = *((__IO uint8_t *)(aligned_addr + i));
			}

			// overwite only the affected part
			offset = addr - aligned_addr;
			chunk = FLASH_WORD_LEN - offset;

			if (chunk > len)
			{
				chunk = len;
			}

			for (uint32_t i = 0; i < chunk; i++)
			{
				flash_word[offset + i] = buff_p[i];
			}

			// write the flash word
			status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_QUADWORD, aligned_addr, (uint32_t) flash_word);

			LL_ICACHE_Invalidate();

			if (status != HAL_OK)
			{
				HAL_FLASH_Lock();
				return -2;
			}

			addr += chunk;
			buff_p += chunk;
			len -= chunk;
		}
	}

	HAL_FLASH_Lock();
	return 0;
}

 

I can perform erase and program operations correctly, but I have an NMI exception during the verify operations, when trying to read back a particular flash location, due to an ECCD event.

I checked that the flash content is the same whether the applicaton is programmed via JTAG/SWD or bootloader, but in the first case I don't have the problem.

In particular, at 0x08040400 is placed the application CRC (0x9968) and the exception occours when reading the address 0x08040402 where are placed the padding at zero, as higlighted in bold, below:

[0x08040400 - 0x0804040F]: 68 99 00 00 | FF FF FF FF | 56 2E 31 30 | 31 00 00 00

 

MEMORY
{
  ...
  CRC           (r)		: ORIGIN = 0x8040400,   LENGTH = 0x00008
  ...
}

.crc :
{
  . = ALIGN(4);
  KEEP(*(.crc))
  . = ALIGN(4);
} >CRC
const uint16_t crc __attribute__((section(".crc"))) = {0x9968};

 

In particular, I have seen that the .crc section code is received by the bootloader as 4 byte segment, that being shorter than the 16 byte flash-word, activates the following read-modify-write procedure:

1. Read 16 bytes flash-word at address 0x08040400 in a buffer.
2. Overwrite the first 4 location of the buffer, with the CRC + padding.
3. Write back the 16 bytes buffer to flash at address 0x08040400.

 

Thank you,
Carlo

0 REPLIES 0