2021-11-03 07:03 AM
Hey guys.
After having a lot of problems i had with fmc and nand flash finally i made it work.
But when i was looking at HAL_NAND_Read_Page_8b hal function i saw that instead of using CMD_AREA for read command 0x00 it uses ADDR_AREA. But read and write page works fine.
Is it a bug or something that i dont know?
Here is the function:
HAL_StatusTypeDef HAL_NAND_Write_Page_8b(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer,
uint32_t NumPageToWrite)
{
uint32_t index;
uint32_t tickstart;
uint32_t deviceaddress;
uint32_t numpageswritten = 0U;
uint32_t nandaddress;
uint32_t nbpages = NumPageToWrite;
uint8_t *buff = pBuffer;
/* Check the NAND controller state */
if (hnand->State == HAL_NAND_STATE_BUSY)
{
return HAL_BUSY;
}
else if (hnand->State == HAL_NAND_STATE_READY)
{
/* Process Locked */
__HAL_LOCK(hnand);
/* Update the NAND controller state */
hnand->State = HAL_NAND_STATE_BUSY;
/* Identify the device address */
deviceaddress = NAND_DEVICE;
/* NAND raw address calculation */
nandaddress = ARRAY_ADDRESS(pAddress, hnand);
/* Page(s) write loop */
while ((nbpages != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr))))
{
/* Send write page command sequence */
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A;
__DSB();
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0;
__DSB();
/* Cards with page size <= 512 bytes */
if ((hnand->Config.PageSize) <= 512U)
{
if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
{
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
__DSB();
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
__DSB();
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
__DSB();
}
else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
{
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
__DSB();
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
__DSB();
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
__DSB();
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
__DSB();
}
}
else /* (hnand->Config.PageSize) > 512 */
{
if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
{
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
__DSB();
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
__DSB();
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
__DSB();
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
__DSB();
}
else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
{
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
__DSB();
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
__DSB();
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
__DSB();
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
__DSB();
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
__DSB();
}
}
/* Write data to memory */
for (index = 0U; index < hnand->Config.PageSize; index++)
{
*(__IO uint8_t *)deviceaddress = *buff;
buff++;
__DSB();
}
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1;
__DSB();
/* Get tick */
tickstart = HAL_GetTick();
/* Read status until NAND is ready */
while (HAL_NAND_Read_Status(hnand) != NAND_READY)
{
if ((HAL_GetTick() - tickstart) > NAND_WRITE_TIMEOUT)
{
/* Update the NAND controller state */
hnand->State = HAL_NAND_STATE_ERROR;
/* Process unlocked */
__HAL_UNLOCK(hnand);
return HAL_TIMEOUT;
}
}
/* Increment written pages number */
numpageswritten++;
/* Decrement pages to write */
nbpages--;
/* Increment the NAND address */
nandaddress = (uint32_t)(nandaddress + 1U);
}
/* Update the NAND controller state */
hnand->State = HAL_NAND_STATE_READY;
/* Process unlocked */
__HAL_UNLOCK(hnand);
}
else
{
return HAL_ERROR;
}
return HAL_OK;
}
2021-11-03 07:04 AM
I mean this line of code:
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
should be rewrite as:
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = 0x00U;
or not.
2021-11-03 11:24 AM
I suppose it depends on the specific NAND ICs it's designed to work with.
Sector zero on NAND's tends to be a special case, as it's always supposed to be readable (error-free) and regardless of the size/geometry of the NAND array.
Best to code a solution based on the parts you're using, and a thorough reading and understanding of the data sheet.
I don't know how well this is currently tested/maintained, nor the broadness of the NAND support. ST uses to own a NAND fab, I think they sold it or spun it out to Micron or Numonyx (2008)