Skip to main content
omisys
Associate
February 22, 2019
Question

How to get the FMC ECC working with NAND

  • February 22, 2019
  • 5 replies
  • 3263 views

I'm using an STM32F765 and a toshiba NAND chip via FMC. I want to use the hardware ECC, but the ECCR register is always empty. My fmc init looks like this:

 /** Perform the NAND1 memory initialization sequence

 */

 hnand1.Instance = FMC_NAND_DEVICE;

 /* hnand1.Init */

 hnand1.Init.NandBank = FMC_NAND_BANK3;

 hnand1.Init.Waitfeature = FMC_NAND_WAIT_FEATURE_ENABLE;

 hnand1.Init.MemoryDataWidth = FMC_NAND_MEM_BUS_WIDTH_8;

 hnand1.Init.EccComputation = FMC_NAND_ECC_ENABLE;

 hnand1.Init.ECCPageSize = FMC_NAND_ECC_PAGE_SIZE_256BYTE;

 hnand1.Init.TCLRSetupTime = 2;

 hnand1.Init.TARSetupTime = 2;

I do the following in a loop:

HAL_NAND_ECC_Enable(&hnand1);

write 256 bytes

HAL_NAND_GetECC

HAL_NAND_ECC_Disable(&hnand1);

This results in the ECCR register always being 0. The ECC computation is enabled in cube. I'm using bank 3 which should be supported. What to do?

This topic has been closed for replies.

5 replies

Mohamed Aymen HZAMI
ST Employee
February 22, 2019

Hello,

You can try to use this example in the firmware package STM32Cube_FW_F7 under :

  • Repository\STM32Cube_FW_F7_V1.14.0\Projects\STM32F769I_EVAL\Examples\FMC

This example shows how to configure the FMC controller to access the NOR memory.

Best Regards,

Mohamed Aymen.

Tesla DeLorean
Guru
February 22, 2019

This seems like an answer to a different question.

Need examples of ECC syndrome generation and/or checking for NAND devices.

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
omisys
omisysAuthor
Associate
February 22, 2019

Hi,

I have no problems with using the NAND flash. Reading and writing is both working. My only problem is the hardware ECC which seems to not be doing anything.

Tesla DeLorean
Guru
February 22, 2019

Back in the day I think there where SPL NAND examples for the F2 and F4 series parts, however as I recall it used obsolete algorithms for different architectures, and at a time where the NAND parts themselves could auto generate the required syndrome bytes as part of the write process, ie you wrote the sectors, and then wrote the computed ECC from buffers. Worked well if you have integrity at a bus level.

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
omisys
omisysAuthor
Associate
February 25, 2019

How is this supposed to help me? I'm looking for someone who has used the hardware ECC from the FMC to maybe show me an example or point me to the right direction.

florin_o
Visitor II
January 26, 2020

I have the same problem on my side.

Reading and writing works but cannot use hardware ECC.

I'm testing using the Open407 board.

Tesla DeLorean
Guru
January 26, 2020

And what NAND device is that using? Does the sector format and ECC byte scheme match that supported by the F4 generator?

Given the lack you useful responses from ST, you might want to file an "Online Support Request" ticket, or find a local FAE (support engineer) with specific NAND usage experience.

I seem to recall the SPL or EVAL series examples having some NAND support, but these would have been for antiquated NAND devices. The actual correction would need to be done in software.

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
florin_o
Visitor II
January 27, 2020

The NAND device is K9F1G08U0E.

Hungyin
Associate
February 16, 2020
static uint8_t buffer[2048];
 
static void test(void)
{
 int i;
 uint32_t ecc[2];
 NAND_AddressTypeDef addr;
 
 memset(buffer, 0, sizeof(buffer));
 addr.Plane = 0;
 addr.Block = 0;
 addr.Page = 2;
 HAL_NAND_ECC_Enable(&hnand);
 HAL_NAND_Read_Page_8b(&hnand, &addr, buffer, 1);
 HAL_NAND_GetECC(&hnand, &ecc[0], HAL_MAX_DELAY);
 HAL_NAND_ECC_Disable(&hnand);
 HAL_NAND_Read_SpareArea_8b(&hnand, &addr, (uint8_t *)&ecc[1], 1);
 
 printf("ECC=%#x, %#x\n", ecc[0], ecc[1]);
 if (ecc[0] != ecc[1])
 printf("ECC error!\n");
 
 for (i = 0; i < sizeof(buffer); i++)
 {
 if (buffer[10] != 0x8a || (i != 10 && buffer[i] != (i & 0xff)))
 printf("(%d) buffer[%#x]=%#x\n", i, i, buffer[i]);
 }
}
 
static void write_test(void)
{
 int i;
 uint32_t ecc;
 NAND_AddressTypeDef addr;
 
 for (i = 0; i < sizeof(buffer); i++)
 {
 buffer[i] = i & 0xff;
 if (i == 10)
 buffer[i] |= 0x80;
 }
 
 addr.Plane = 0;
 addr.Block = 0;
 addr.Page = 2;
 HAL_NAND_ECC_Enable(&hnand);
 HAL_NAND_Write_Page_8b(&hnand, &addr, buffer, 1);
 HAL_NAND_GetECC(&hnand, &ecc, HAL_MAX_DELAY);
 HAL_NAND_ECC_Disable(&hnand);
 HAL_NAND_Write_SpareArea_8b(&hnand, &addr, (uint8_t *)&ecc, 1);
 
 printf("written! ECC=%#x\n", ecc);
}

For data: 00 01 02 03 04 ... FE FF 00 01 02 ..... FD FE FF (2048 bytes)

The computed ECC code is 0.

Buf if we change data[10] from 0x0a to 0x8a, the ECC will be 0x5555666a.

MMaza.1
Visitor II
December 5, 2022

Hey

If you refer to the reference manual you will understand that the way ECC works is like this:

1- Enable ECC

2- Write to a page

3- Read ECC

4- Disable ECC

5- Enable ECC

6- Read the same page (In order to make sure the written data is what you wanted to be written)

7- Disable ECC

8- Compare ECC's

if they are the same then the data is written successfully without any errors.

Like the code below:

 NAND_AddressTypeDef myAddress;
 uint8_t myPage[2048] = {0};
 uint32_t ECCval1 = 0, ECCval2 = 0;
 
	// ECC is used to make sure the data is correctly "WRITTEN"
 
	myAddress.Plane = 0;
	myAddress.Block = 0;
	myAddress.Page = 3;	
 
	for(uint16_t i=0 ; i<2048 ; i++)
		myPage[i] = 0xFF;
 
	myPage[0] = 0x0A;
	myPage[1] = 0x0B;
	myPage[2] = 0x0C;
	myPage[3] = 0x0D;
	myPage[4] = 0x0E;
 
	HAL_NAND_ECC_Enable(&hnand1);	
	
	if(HAL_NAND_Write_Page_8b(&hnand1,&myAddress,myPage,1) == HAL_OK)
	{
		printf("Page write OK!\n");
		if(HAL_NAND_GetECC(&hnand1,&ECCval1,1000) == HAL_OK)
		{
			printf("ECC Read OK!\n");
		}
		else
		{
			printf("ECC Read EEROR!\n");
		}
	}
	else
	{
		printf("Page write ERROR...\n");
	}
 
	HAL_NAND_ECC_Disable(&hnand1);
	
	HAL_Delay(50);	//###########################3
	
	HAL_NAND_ECC_Enable(&hnand1);	
	
	if(HAL_NAND_Read_Page_8b(&hnand1,&myAddress,myPage,1) == HAL_OK)
	{
		printf("Page read OK!\n");
		if(HAL_NAND_GetECC(&hnand1,&ECCval2,1000) == HAL_OK)
		{
			printf("ECC Read OK!\n");
		}
		else
		{
			printf("ECC Read EEROR!\n");
		}
	}
	else
	{
		printf("Page read ERROR...\n");
	}
 
	HAL_NAND_ECC_Disable(&hnand1);
	
	if(ECCval1 == ECCval2 != 0)
	{
		printf("\nECC's Match....!\n");
	}
	else
	{
		printf("\nECC's DO NOT Match\n");
	}