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

1 ACCEPTED SOLUTION

Accepted Solutions

Hello @Dor_RH,
the problem was with my program function, which allowed to program the same 16 byte flash-word in two steps rather than in a single step.

Even if during the second step I paid attention to reiterate the value of the bytes written in the first step, the ECC for the same flash word is calculated two times, and the second time it won't be programmed correctly, as it is not at 0xFF any longer.

This problem was difficoult to investigate because the HAL_FLASH_Program() won't signal any error when it fails to program the ECC.

Regards,
Carlo

 

 

View solution in original post

2 REPLIES 2
Dor_RH
ST Employee

Hello @CTabo.1,

NMIs during verify operations can be caused by hardware issues such as voltage drops or instability.

They can also result from memory access violations, such as when the code tries to read or write to protected or invalid memory areas.

To read/write data from/to flash memory with HAL functions, I advise you to get inspired from an available example such as FLASH_FastProgram under STM32CubeH5

This example can help you to understand and use the FLASH HAL API to erase and fast program the internal Flash.

I hope my answer has helped you. When your question is answered, please select this topic as the solution that answered you, as it will help others find that answer faster.

Thanks for your contribution.

Dor_RH

Hello @Dor_RH,
the problem was with my program function, which allowed to program the same 16 byte flash-word in two steps rather than in a single step.

Even if during the second step I paid attention to reiterate the value of the bytes written in the first step, the ECC for the same flash word is calculated two times, and the second time it won't be programmed correctly, as it is not at 0xFF any longer.

This problem was difficoult to investigate because the HAL_FLASH_Program() won't signal any error when it fails to program the ECC.

Regards,
Carlo