Skip to main content
MLind.5
Visitor II
August 23, 2021
Question

Read/write from stm32f4 to an external SLC NAND flash - S34ML02G through HAL and FSMC

  • August 23, 2021
  • 0 replies
  • 1380 views

Hi,

I am using a custom board equipped with an stm32f417VGT and an external SLC NAND flash (more specifically S34ML02G).

Through reading and writing from GPIOs I successfully "bit-banged" the read and write operations between the MCU and the NAND flash.

However, when I tried to initialize the drive and read the flash ID (which works in the bit-banged version) through the library FSMC / HAL_NAND driver it does neither return the correct ID or the correct data (it actually prints my message "NandFlash Read Write Failed") See 3rd code snippet down below.

What I do want to accomplish is to use the FSMC to read and write data from and to the NAND flash.

In the FSMC driver, I do need to specify the correct read timings.

These calculations are as follow (found in a seprate datasheet):

(SET + 1) x tHCLK ≥ max (tCS, tCLS, tALS, tCLR, tAR) - tWP

(WAIT + 1) x tHCLK ≥ max (tWP, tRP)

(HIZ) x tHCLK ≥ max (tCS, tALS, tCLS) + (tWP - tDS)

(HOLD) x tHCLK ≥ max (tCH, tCLH, tALH)

((WAIT + 1) + (HOLD) + (SET + 1)) x tHCLK ≥ max (tWC/RC)

The time variable taken from the clock frequency I use in the project:

tHCLK = 5,9523480952380952e-9s = (1 / 168000000)

The time variables for S34ML02G are as follow (from the flash's datasheet):

tALH = 5 e-9

tALS = 10e-9 s

tAR = 10e-9 s

tCH = 5 e-9

tCLH = 5 e-9

tCLR = 10e-9 s

tCLS = 10e-9 s

tCS = 20e-9 s

tDS = 10 e-9

tRP = 12 e-9 s

tWP = 12e-9 s

Hence, I get the formulas:

set = max(tcs,tcls,tals,tclr,tar)-twp / thclk - 1

wait = max(tWP, tRP) / tCHLK - 1

HIZ = (max(tCS, tALS, tCLS) + (tWP - tDS)) / tHCLK

HOLD = max(tch, tCLH, tALH) / tHCLK

From the formulas above I get the values:

set = 1/3 e-9 = 0

wait = 12/6 - 1 = 1

HiZ = 20 + (12-10) / 6 = 22/6 = 4,4 = 4

HOLD = 5/6 = 0

At this point I have not got the FSMC to work, therefore I wonder, Am I missing something in my calculations or code?

Am I doing something wrong during the initialization or read/write functions?

Furthermore, do you have any suggestions on how to continue the debugging?

Code for initialization of the pins for FSMC

GPIO_InitTypeDef GPIO_InitStruct ={0};
 if (FSMC_Initialized) {
 return;
 }
 FSMC_Initialized = 1;
 
 /* Peripheral clock enable */
 __HAL_RCC_FSMC_CLK_ENABLE();
 
 /** FSMC GPIO Configuration
 PE7 ------> FSMC_D4
 PE8 ------> FSMC_D5
 PE9 ------> FSMC_D6
 PE10 ------> FSMC_D7
 PD11 ------> FSMC_CLE
 PD12 ------> FSMC_ALE
 PD14 ------> FSMC_D0
 PD15 ------> FSMC_D1
 PD0 ------> FSMC_D2
 PD1 ------> FSMC_D3
 PD4 ------> FSMC_NOE
 PD5 ------> FSMC_NWE
 PD6 ------> FSMC_NWAIT
 PD7 ------> FSMC_NCE2
 */
 GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10;
 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
 GPIO_InitStruct.Alternate = GPIO_AF12_FSMC;
 HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
 
 GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_14|GPIO_PIN_15
 |GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5
 |GPIO_PIN_6|GPIO_PIN_7;
 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
 GPIO_InitStruct.Alternate = GPIO_AF12_FSMC;
 HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

Code for initialisation of FSMC

FSMC_NAND_PCC_TimingTypeDef ComSpaceTiming = {0};
	FSMC_NAND_PCC_TimingTypeDef AttSpaceTiming = {0};
 
	/** Perform the NAND1 memory initialization sequence
	*/
	hnand1->Instance = FSMC_NAND_DEVICE;
	/* hnand1.Init */
	hnand1->Init.NandBank = FSMC_NAND_BANK2;
	hnand1->Init.Waitfeature = FSMC_NAND_PCC_WAIT_FEATURE_DISABLE;
	hnand1->Init.MemoryDataWidth = FSMC_NAND_PCC_MEM_BUS_WIDTH_8;
	hnand1->Init.EccComputation = FSMC_NAND_ECC_DISABLE;
	hnand1->Init.ECCPageSize = FSMC_NAND_ECC_PAGE_SIZE_256BYTE;
	hnand1->Init.TCLRSetupTime = 0;
	hnand1->Init.TARSetupTime = 0;
	/* hnand1.Config */
	hnand1->Config.PageSize = 2048;
	hnand1->Config.SpareAreaSize = 64;
	hnand1->Config.BlockSize = 128;
	hnand1->Config.BlockNbr = 16;
	hnand1->Config.PlaneNbr = 2;
	hnand1->Config.PlaneSize = 1024;
	hnand1->Config.ExtraCommandEnable = DISABLE;
	/* ComSpaceTiming */
	ComSpaceTiming.SetupTime = 0;
	ComSpaceTiming.WaitSetupTime = 1;
	ComSpaceTiming.HoldSetupTime = 0;
	ComSpaceTiming.HiZSetupTime = 4;
	/* AttSpaceTiming */
	AttSpaceTiming.SetupTime = 0;
	AttSpaceTiming.WaitSetupTime = 1;
	AttSpaceTiming.HoldSetupTime = 0;
	AttSpaceTiming.HiZSetupTime = 4;
 
	if (HAL_NAND_Init(hnand1, &ComSpaceTiming, &AttSpaceTiming) != HAL_OK)
	{
		printf("Could not initialize flash static memory controller\n");
	}

Code for reading ID and data:

static uint8_t TxBuffer [2048];
static uint8_t RxBuffer [2048];
NAND_HandleTypeDef hnand1;
NAND_IDTypeDef NAND_ReadID_handle = { 0 };
 
	HAL_NAND_Reset(&hnand1);
 HAL_Delay(100);
 
 /* Read the NAND memory ID */
	HAL_NAND_Read_ID(&hnand1,&NAND_ReadID_handle);
 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 data */
 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 Failed \r\n");
 while(1);
 }

Best regards,

ML.

This topic has been closed for replies.