cancel
Showing results for 
Search instead for 
Did you mean: 

why nand flash doesn't respond properly to stm32f429igt6?

ali rostami
Associate III

I designed a board for stm32f429 discovery which has a nand flash on it and use fmc for working with.

The nand flash part number is K9F2G08U0C. I've worked with it before and use it with stm32f103zet6 by fsmc.

But now seems that the fmc can not interact with it correctly.

Here is my fmc init function:

static void MX_FMC_Init(void)
{
	FMC_NAND_PCC_TimingTypeDef ComSpaceTiming;
	FMC_NAND_PCC_TimingTypeDef AttSpaceTiming;
	FMC_SDRAM_TimingTypeDef SdramTiming;
 
	/** Perform the NAND1 memory initialization sequence
	 */
	hnand1.Instance = FMC_NAND_DEVICE;
	/* hnand1.Init */
	hnand1.Init.NandBank = FMC_NAND_BANK2;
	hnand1.Init.Waitfeature = FMC_NAND_PCC_WAIT_FEATURE_ENABLE;
	hnand1.Init.MemoryDataWidth = FMC_NAND_PCC_MEM_BUS_WIDTH_8;
	hnand1.Init.EccComputation = FMC_NAND_ECC_DISABLE;
	hnand1.Init.ECCPageSize = FMC_NAND_ECC_PAGE_SIZE_512BYTE;
	hnand1.Init.TCLRSetupTime = 2;
	hnand1.Init.TARSetupTime = 2;
	/* hnand1.Config */
	hnand1.Config.PageSize = 2048;
	hnand1.Config.SpareAreaSize = 64;
	hnand1.Config.BlockSize = 64;
	hnand1.Config.BlockNbr = 2048;
	hnand1.Config.PlaneNbr = 2;
	hnand1.Config.PlaneSize = 1024;
	hnand1.Config.ExtraCommandEnable = DISABLE;
	/* ComSpaceTiming */
	ComSpaceTiming.SetupTime = 4;
	ComSpaceTiming.WaitSetupTime = 2;
	ComSpaceTiming.HoldSetupTime = 2;
	ComSpaceTiming.HiZSetupTime = 4;
	/* AttSpaceTiming */
	AttSpaceTiming.SetupTime = 4;
	AttSpaceTiming.WaitSetupTime = 2;
	AttSpaceTiming.HoldSetupTime = 2;
	AttSpaceTiming.HiZSetupTime = 4;
 
	if (HAL_NAND_Init(&hnand1, &ComSpaceTiming, &AttSpaceTiming) != HAL_OK)
	{
		Error_Handler( );
	}
 
	/** Perform the SDRAM1 memory initialization sequence
	 */
	hsdram1.Instance = FMC_SDRAM_DEVICE;
	/* hsdram1.Init */
	hsdram1.Init.SDBank = FMC_SDRAM_BANK2;
	hsdram1.Init.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_8;
	hsdram1.Init.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_12;
	hsdram1.Init.MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_16;
	hsdram1.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4;
	hsdram1.Init.CASLatency = FMC_SDRAM_CAS_LATENCY_3;
	hsdram1.Init.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE;
	hsdram1.Init.SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_2;
	hsdram1.Init.ReadBurst = FMC_SDRAM_RBURST_DISABLE;
	hsdram1.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_1;
	/* SdramTiming */
	SdramTiming.LoadToActiveDelay = 2;
	SdramTiming.ExitSelfRefreshDelay = 7;
	SdramTiming.SelfRefreshTime = 4;
	SdramTiming.RowCycleDelay = 7;
	SdramTiming.WriteRecoveryTime = 3;
	SdramTiming.RPDelay = 2;
	SdramTiming.RCDDelay = 2;
 
	if (HAL_SDRAM_Init(&hsdram1, &SdramTiming) != HAL_OK)
	{
		Error_Handler( );
	}
 
}

and this is the code I wrote for testing it:

{
		static NAND_AddressTypeDef WriteReadAddr;
		static NAND_IDTypeDef NAND_ID;
		static uint8_t TxBuffer [2048];
		static uint8_t RxBuffer [2048];
 
		HAL_NAND_Reset(&hnand1);
		HAL_Delay(100);
 
		/* Read the NAND memory ID */
		HAL_NAND_Read_ID(&hnand1, &NAND_ID);
		HAL_Delay(100);
		
		/* Fill the buffer to send */
		for (int i = 0; i < 2048; i++ )
		{
			RxBuffer[i] = 0;
		}
 
		/* Fill the buffer to send */
		for (int i = 0; i < 2048; i++ )
		{
			TxBuffer[i] = i;
		}
 
		/* NAND memory address to write to */
		WriteReadAddr.Plane = 0;
		WriteReadAddr.Block = 2;
		WriteReadAddr.Page = 0;
 
		/* Erase the NAND first Block */
		if( HAL_NAND_Erase_Block(&hnand1, &WriteReadAddr) != HAL_OK)
		{
 
			while(1);
		}
		HAL_Delay(100);
 
 
		/* Write data to FMC NAND memory */
		if(HAL_NAND_Write_Page(&hnand1, &WriteReadAddr, TxBuffer, 1) != HAL_OK)
		{
			while(1);
		}
		HAL_Delay(100);
		
		/* Read data from FMC NAND memory */
		if(HAL_NAND_Read_Page(&hnand1, &WriteReadAddr, RxBuffer, 1) != HAL_OK)
		{
			while(1);
		}
 
		/* check date */
		if(memcmp(TxBuffer,RxBuffer,sizeof(TxBuffer)) == 0 )
			printf("\r\n\r\n NandFlash Read Write Test OK\r\n");
		else
		{
			printf("\r\n\r\n NandFlash Read Write False\r\n");
			while(1);
		}
 
	}

2 REPLIES 2
ali rostami
Associate III

And BTW as the datasheet of this ic is not compatible with the stm32f4xx_hal_nand.c library, I changed some codes as you can see here:

HAL_StatusTypeDef HAL_NAND_Read_Page_8b(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumPageToRead)
{   
  __IO uint32_t index  = 0U;
  uint32_t tickstart = 0U;
  uint32_t deviceaddress = 0U, size = 0U, numPagesRead = 0U, nandaddress = 0U;
  
  /* Process Locked */
  __HAL_LOCK(hnand); 
  
  /* Check the NAND controller state */
  if(hnand->State == HAL_NAND_STATE_BUSY)
  {
     return HAL_BUSY;
  }
  
  /* Identify the device address */
  if(hnand->Init.NandBank == FMC_NAND_BANK2)
  {
    deviceaddress = NAND_DEVICE1;
  }
  else
  {
    deviceaddress = NAND_DEVICE2;
  }
 
  /* Update the NAND controller state */
  hnand->State = HAL_NAND_STATE_BUSY;
  
  /* NAND raw address calculation */
  nandaddress = ARRAY_ADDRESS(pAddress, hnand);
 
  /* Page(s) read loop */  
  while((NumPageToRead != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr))))
  {
    /* update the buffer size */
    size = (hnand->Config.PageSize) + ((hnand->Config.PageSize) * numPagesRead);
    
    /* Send read page command sequence */
    *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A;
    NAND_Delay(1);
    /* 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)) = 0x00;
//        *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
//        *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
//      }
//      else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
//      {
//        *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00;
//        *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
//        *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
//        *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
//      }
//    }
//    else /* (hnand->Config.PageSize) > 512 */
    {
//      if (((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) <= 65535U)
//      {
//        *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00;
//        *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00;
//        *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
//        *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
//      }
//      else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
      {
        *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00;
        NAND_Delay(1);
        *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00;
        NAND_Delay(1);
        *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
        NAND_Delay(1);
        *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
        NAND_Delay(1);
        *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
        NAND_Delay(1);
      }
    }
  
    *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA))  = NAND_CMD_AREA_TRUE1;
    NAND_Delay(20);
 
    while (!HAL_GPIO_ReadPin(GPIOD, GPIO_PIN_6));//pd6 is connected to r/b pin of nand flash
    NAND_Delay(20);
      
    /* Check if an extra command is needed for reading pages  */
    if(hnand->Config.ExtraCommandEnable == ENABLE)
    {
      /* 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)
        {
          return HAL_TIMEOUT; 
        }
      }
      
      /* Go back to read mode */
      *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = ((uint8_t)0x00);
    //  __DSB();
    }
    
    /* Get Data into Buffer */    
    for(; index < size; index++)
    {
      *(uint8_t *)pBuffer++ = *(uint8_t *)deviceaddress;
    }
    
    /* Increment read pages number */
    numPagesRead++;
    
    /* Decrement pages to read */
    NumPageToRead--;
    
    /* 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);
 
  return HAL_OK;
}
/****************************************************************************/
HAL_StatusTypeDef HAL_NAND_Write_Page_8b(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumPageToWrite)
{
  __IO uint32_t index = 0U;
  uint32_t tickstart = 0U;
  uint32_t deviceaddress = 0U, size = 0U, numPagesWritten = 0U, nandaddress = 0U;
  
  /* Process Locked */
  __HAL_LOCK(hnand);  
 
  /* Check the NAND controller state */
  if(hnand->State == HAL_NAND_STATE_BUSY)
  {
     return HAL_BUSY;
  }
  
  /* Identify the device address */
  if(hnand->Init.NandBank == FMC_NAND_BANK2)
  {
    deviceaddress = NAND_DEVICE1;
  }
  else
  {
    deviceaddress = NAND_DEVICE2;
  }
  
  /* Update the NAND controller state */ 
  hnand->State = HAL_NAND_STATE_BUSY;
  
  /* NAND raw address calculation */
  nandaddress = ARRAY_ADDRESS(pAddress, hnand);
    
  /* Page(s) write loop */
  while((NumPageToWrite != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr))))
  {
    /* update the buffer size */
    size = hnand->Config.PageSize + ((hnand->Config.PageSize) * numPagesWritten);
    
    /* Send write page command sequence */
//    *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A;
    *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0;
    NAND_Delay(10);
    /* 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)) = 0x00;
//        *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
//        *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
//      }
//      else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
//      {
//        *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00;
//        *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
//        *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
//        *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
//      }
//    }
//    else /* (hnand->Config.PageSize) > 512 */
    {
//      if (((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) <= 65535U)
//      {
//        *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00;
//        *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00;
//        *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
//        *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
//      }
//      else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
      {
        *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00;
        NAND_Delay(10);
        *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00;
        NAND_Delay(10);
        *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
        NAND_Delay(10);
        *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
        NAND_Delay(10);
     //   __DSB();
        *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
        NAND_Delay(10);
    //    __DSB();
      }
    }
  
 
    /* Write data to memory */
    for(; index < size; index++)
    {
      *(__IO uint8_t *)deviceaddress = *(uint8_t *)pBuffer++;
      NAND_Delay(10);
    }
   
    *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1;
    NAND_Delay(10);
    
    /* Read status until NAND is ready */
    while(HAL_NAND_Read_Status(hnand) != NAND_READY)
    {
      /* Get tick */
      tickstart = HAL_GetTick();
      
      if((HAL_GetTick() - tickstart ) > NAND_WRITE_TIMEOUT)
      {
        return HAL_TIMEOUT; 
      }
    }
 
    /* Increment written pages number */
    numPagesWritten++;
    
    /* Decrement pages to write */
    NumPageToWrite--;
    
    /* 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);
  
  return HAL_OK;
}
 

ali rostami
Associate III
/****************************************************************************/
HAL_StatusTypeDef HAL_NAND_Read_ID(NAND_HandleTypeDef *hnand, NAND_IDTypeDef *pNAND_ID)
{
  __IO uint32_t data = 0U;
  __IO uint32_t data1 = 0U;
  uint32_t deviceaddress = 0U;
 
  /* Process Locked */
  __HAL_LOCK(hnand);  
  
  /* Check the NAND controller state */
  if(hnand->State == HAL_NAND_STATE_BUSY)
  {
     return HAL_BUSY;
  }
  
  /* Identify the device address */
  if(hnand->Init.NandBank == FMC_NAND_BANK2)
  {
    deviceaddress = NAND_DEVICE1;
  }
  else
  {
    deviceaddress = NAND_DEVICE2;
  }
  
  /* Update the NAND controller state */ 
  hnand->State = HAL_NAND_STATE_BUSY;
  
  /* Send Read ID command sequence */   
  *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA))  = NAND_CMD_READID;
  *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00;
 
  /* Read the electronic signature from NAND flash */
//#ifdef FSMC_PCR2_PWID
//  if (hnand->Init.MemoryDataWidth == FSMC_NAND_PCC_MEM_BUS_WIDTH_8)
//#else /* FMC_PCR2_PWID is defined */
//  if (hnand->Init.MemoryDataWidth == FMC_NAND_PCC_MEM_BUS_WIDTH_8)
//#endif
//  {
//    data = *(__IO uint32_t *)deviceaddress;
//
//    /* Return the data read */
//    pNAND_ID->Maker_Id   = ADDR_1ST_CYCLE(data);
//    pNAND_ID->Device_Id  = ADDR_2ND_CYCLE(data);
//    pNAND_ID->Third_Id   = ADDR_3RD_CYCLE(data);
//    pNAND_ID->Fourth_Id  = ADDR_4TH_CYCLE(data);
//  }
//  else
//  {
    data = *(__IO uint32_t *)deviceaddress;
    data1 = *((__IO uint32_t *)deviceaddress + 4U);
    
    /* Return the data read */
    pNAND_ID->Maker_Id   = ADDR_1ST_CYCLE(data);
    pNAND_ID->Device_Id  = ADDR_3RD_CYCLE(data);
    pNAND_ID->Third_Id   = ADDR_1ST_CYCLE(data1);
    pNAND_ID->Fourth_Id  = ADDR_3RD_CYCLE(data1);
//  }
  
  /* Update the NAND controller state */ 
  hnand->State = HAL_NAND_STATE_READY;
  
  /* Process unlocked */
  __HAL_UNLOCK(hnand);
   
  return HAL_OK;
}