Skip to main content
Arman Ilmak
Senior
November 3, 2021
Question

Is it a bug in NAND FMC read_page or write_page that works fine?

  • November 3, 2021
  • 2 replies
  • 1197 views

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

This topic has been closed for replies.

2 replies

Arman Ilmak
Senior
November 3, 2021

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.

Tesla DeLorean
Guru
November 3, 2021

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)

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..