cancel
Showing results for 
Search instead for 
Did you mean: 

How to get the FMC ECC working with NAND

omisys
Associate II

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?

11 REPLIES 11
Hungyin
Associate II
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
Associate

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");
	}