2019-02-22 06:52 AM
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?
2020-02-16 02:10 AM
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.
2022-12-05 02:35 AM
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");
}