cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F407 4GB NAND Flash ECC computation while read and write are different, but the data is the same.

hypnotriod
Associate II

This is the code I'm using to read the page of 16 data chunks of 256 bytes each:

#define K9xxG08_ECC_Enable()			FSMC_NAND_DEVICE->PCR2 |= FSMC_PCR2_ECCEN
#define K9xxG08_ECC_Disable()		        FSMC_NAND_DEVICE->PCR2 &= ~FSMC_PCR2_ECCEN
#define K9xxG08_FIFO_Wait()			while ((FSMC_NAND_DEVICE->SR2 & FSMC_SR2_FEMPT) != FSMC_SR2_FEMPT){};
#define K9xxG08_ECC_Read()			(FSMC_NAND_DEVICE->ECCR2 & K9xxG08_ECC_MASK)
 
void K9xxG08_ReadPage(uint8_t *pBuffer, uint32_t pageAddress)
{
	uint32_t i;
	uint32_t endAddr;
	uint32_t ecc;
	uint32_t eccBuff[K9LBG08_ECC_CHUNKS_NUM];
 
	*(__IO uint8_t *)((uint32_t)(K9xxG08_FSMC_NAND_DEVICE | CMD_AREA))  = K9xxG08_CMD_READ0; 
	*(__IO uint8_t *)((uint32_t)(K9xxG08_FSMC_NAND_DEVICE | ADDR_AREA)) = K9xxG08_1st_CYCLE(K9xxG08_PageSize);
	*(__IO uint8_t *)((uint32_t)(K9xxG08_FSMC_NAND_DEVICE | ADDR_AREA)) = K9xxG08_2nd_CYCLE(K9xxG08_PageSize);
	*(__IO uint8_t *)((uint32_t)(K9xxG08_FSMC_NAND_DEVICE | ADDR_AREA)) = K9xxG08_1st_CYCLE(pageAddress);
	*(__IO uint8_t *)((uint32_t)(K9xxG08_FSMC_NAND_DEVICE | ADDR_AREA)) = K9xxG08_2nd_CYCLE(pageAddress);
	*(__IO uint8_t *)((uint32_t)(K9xxG08_FSMC_NAND_DEVICE | ADDR_AREA)) = K9xxG08_3rd_CYCLE(pageAddress);
	*(__IO uint8_t *)((uint32_t)(K9xxG08_FSMC_NAND_DEVICE | CMD_AREA))  = K9xxG08_CMD_READ1;
	
	for (i = 0; i != K9xxG08_EccChunksNum; i++)
	{
		((uint8_t *)&eccBuff[i])[0] = (*(__IO uint8_t *)K9xxG08_FSMC_NAND_DEVICE);
		((uint8_t *)&eccBuff[i])[1] = (*(__IO uint8_t *)K9xxG08_FSMC_NAND_DEVICE);
		((uint8_t *)&eccBuff[i])[2] = (*(__IO uint8_t *)K9xxG08_FSMC_NAND_DEVICE);
		((uint8_t *)&eccBuff[i])[3] = 0;
	}
	
	*(__IO uint8_t *)((uint32_t)(K9xxG08_FSMC_NAND_DEVICE | CMD_AREA))  = K9xxG08_CMD_READ0; 
	*(__IO uint8_t *)((uint32_t)(K9xxG08_FSMC_NAND_DEVICE | ADDR_AREA)) = 0;
	*(__IO uint8_t *)((uint32_t)(K9xxG08_FSMC_NAND_DEVICE | ADDR_AREA)) = 0;
	*(__IO uint8_t *)((uint32_t)(K9xxG08_FSMC_NAND_DEVICE | ADDR_AREA)) = K9xxG08_1st_CYCLE(pageAddress);
	*(__IO uint8_t *)((uint32_t)(K9xxG08_FSMC_NAND_DEVICE | ADDR_AREA)) = K9xxG08_2nd_CYCLE(pageAddress);
	*(__IO uint8_t *)((uint32_t)(K9xxG08_FSMC_NAND_DEVICE | ADDR_AREA)) = K9xxG08_3rd_CYCLE(pageAddress);
	*(__IO uint8_t *)((uint32_t)(K9xxG08_FSMC_NAND_DEVICE | CMD_AREA))  = K9xxG08_CMD_READ1;
	
	for (i = 0; i != K9xxG08_EccChunksNum; i++)
	{
		endAddr = ((uint32_t)pBuffer) + K9xxG08_ECC_CHUNK_SIZE;
		
		K9xxG08_ECC_Enable();
		
		while( ((uint32_t)pBuffer) != endAddr)
			*(uint8_t *)pBuffer++ = *(__IO uint8_t *)K9xxG08_FSMC_NAND_DEVICE;
 
		K9xxG08_FIFO_Wait();
		ecc = K9xxG08_ECC_Read();
		K9xxG08_ECC_Disable();
		
		if (ecc != eccBuff[i])
		{
			performErrorCorrection(ecc, eccBuff[i], pBuffer - K9xxG08_ECC_CHUNK_SIZE);
		}
	}
}

The issue is that I'm getting wrong ecc computed value for 30% of data chunks read. (But the data read is ok)

In other side when I'm writing data chunks to the page, I get 100% correct ecc computed for each chunk:

uint8_t K9xxG08_WritePage(uint8_t *pBuffer, uint32_t pageAddress)
{
	uint32_t i;
        uint32_t status = 0x00;
	uint32_t endAddr;
	uint32_t ecc;
	uint8_t *pEccArea;
  
	*(__IO uint8_t *)((uint32_t)(K9xxG08_FSMC_NAND_DEVICE | CMD_AREA))  = K9xxG08_CMD_WRITE0;
	*(__IO uint8_t *)((uint32_t)(K9xxG08_FSMC_NAND_DEVICE | ADDR_AREA)) = 0;
	*(__IO uint8_t *)((uint32_t)(K9xxG08_FSMC_NAND_DEVICE | ADDR_AREA)) = 0;
	*(__IO uint8_t *)((uint32_t)(K9xxG08_FSMC_NAND_DEVICE | ADDR_AREA)) = K9xxG08_1st_CYCLE(pageAddress);
	*(__IO uint8_t *)((uint32_t)(K9xxG08_FSMC_NAND_DEVICE | ADDR_AREA)) = K9xxG08_2nd_CYCLE(pageAddress);
	*(__IO uint8_t *)((uint32_t)(K9xxG08_FSMC_NAND_DEVICE | ADDR_AREA)) = K9xxG08_3rd_CYCLE(pageAddress);
	
	pEccArea = pBuffer + K9xxG08_PageSize;
	for (i = 0; i != K9xxG08_EccChunksNum; i++)
	{
		endAddr = ((uint32_t)pBuffer) + K9xxG08_ECC_CHUNK_SIZE;
		
		K9xxG08_ECC_Enable();
		
		while( ((uint32_t)pBuffer) != endAddr)
			*(__IO uint8_t *)K9xxG08_FSMC_NAND_DEVICE = *(uint8_t *)pBuffer++;
		
		K9xxG08_FIFO_Wait();
		ecc = K9xxG08_ECC_Read();
		K9xxG08_ECC_Disable();
		
		*pEccArea++ = ((uint8_t *)&ecc)[0];
		*pEccArea++ = ((uint8_t *)&ecc)[1];
		*pEccArea++ = ((uint8_t *)&ecc)[2];
	}
	
	endAddr = ((uint32_t)pBuffer) + K9xxG08_SpareAreaSize;
	
	while( ((uint32_t)pBuffer) != endAddr)
		*(__IO uint8_t *)K9xxG08_FSMC_NAND_DEVICE = *(uint8_t *)pBuffer++;
 
	*(__IO uint8_t *)((uint32_t)(K9xxG08_FSMC_NAND_DEVICE | CMD_AREA)) = K9xxG08_CMD_WRITE1;
	
	while((status & K9xxG08_STATUS_READY) != K9xxG08_STATUS_READY)
	{
		*(__IO uint8_t *)((uint32_t)(K9xxG08_FSMC_NAND_DEVICE | CMD_AREA)) = K9xxG08_CMD_STATUS;
		status = *(__IO uint8_t *)K9xxG08_FSMC_NAND_DEVICE;
	}
	
	return (status & K9xxG08_STATUS_FAIL);
}

So what is wrong with the algorithm? Or should I know something I don't know?

0 REPLIES 0