2020-12-12 02:19 AM
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?