2021-08-23 07:14 AM
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.