AnsweredAssumed Answered

STM32F407 FSMC To NOR Flash Issue

Question asked by shane on Jan 4, 2015
Latest reply on Jan 31, 2015 by shane
Hello,

I'm implementing the FSMC interface to Microchip SST39VF401C NOR Flash and ran into an issue with reading the manufacturer's ID.  My NOR Flash is mapped to FSMC_Bank1_NORSRAM2 and the low 16 address and data lines are multiplexed.  After the FSMC configuration, I send the 3 byte command and attempting to read the MFR ID, I always get the last byte that I sent.  For instance, I write:

    //  Issue the Software Product ID code to SST39VF401C
    *sysAddress(0x555) = 0x00AA;  // write data 0x00AA to device addr 0x555
    *sysAddress(0x2AA) = 0x0055;  // write data 0x0055 to device addr 0x2AA
    *sysAddress(0x555) = 0x0090;  // write data 0x0090 to device addr 0x555

    Delay_150_Nano_Seconds();

    // Read the product ID from SST39VF401C
    mfr_id  = *sysAddress(0x0000);   // get 0x90
    dev_id  = *sysAddress(0x0001);   // get 0x90

Can this symptom lead to a cause that someone already experienced?  I only have a 2 channel scope and was able to see that NADV, CS2, NOE, and NWE are behaving correctly according to Figure 445 and 446 on RM0090.  My FSMC configuration is listed below:

typedef unsigned char  BYTE;  // BYTE is 8-bit in length
typedef unsigned short  WORD;  // WORD is 16-bit in length, ARM
typedef unsigned int  Uint32;  // Uint32 is 32-bit in length, ARM

#define system_base   ((U32)0x64000000)
#define sysAddress(offset) ((volatile WORD *)(system_base + (((WORD)offset)<<1))) //For ARM CPU
#define MAX_TIMEOUT   0x07FFFFFF   // A ceiling constant used by Check_Toggle_

WORD mfr_id;
WORD dev_id;

void ExtFlash_Init(void)
{
 FSMC_NORSRAMInitTypeDef  FSMC_NORSRAMInitStructure;
 FSMC_NORSRAMTimingInitTypeDef  p;
 GPIO_InitTypeDef GPIO_InitStructure;
 
 RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FSMC, ENABLE);

 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOG, ENABLE);

 // address lines
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 |
       GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
 GPIO_PinAFConfig(GPIOD, GPIO_PinSource0, GPIO_AF_FSMC);
 GPIO_PinAFConfig(GPIOD, GPIO_PinSource1, GPIO_AF_FSMC);
 GPIO_PinAFConfig(GPIOD, GPIO_PinSource8, GPIO_AF_FSMC);
 GPIO_PinAFConfig(GPIOD, GPIO_PinSource9, GPIO_AF_FSMC);
 GPIO_PinAFConfig(GPIOD, GPIO_PinSource10, GPIO_AF_FSMC);
 GPIO_PinAFConfig(GPIOD, GPIO_PinSource11, GPIO_AF_FSMC);
 GPIO_PinAFConfig(GPIOD, GPIO_PinSource12, GPIO_AF_FSMC);
 GPIO_PinAFConfig(GPIOD, GPIO_PinSource13, GPIO_AF_FSMC);
 GPIO_PinAFConfig(GPIOD, GPIO_PinSource14, GPIO_AF_FSMC);
 GPIO_PinAFConfig(GPIOD, GPIO_PinSource15, GPIO_AF_FSMC);
 GPIO_Init(GPIOD, &GPIO_InitStructure);

 // address lines (continue)
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 |
       GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
 GPIO_PinAFConfig(GPIOE, GPIO_PinSource3, GPIO_AF_FSMC);
 GPIO_PinAFConfig(GPIOE, GPIO_PinSource7, GPIO_AF_FSMC);
 GPIO_PinAFConfig(GPIOE, GPIO_PinSource8, GPIO_AF_FSMC);
 GPIO_PinAFConfig(GPIOE, GPIO_PinSource9, GPIO_AF_FSMC);
 GPIO_PinAFConfig(GPIOE, GPIO_PinSource10, GPIO_AF_FSMC);
 GPIO_PinAFConfig(GPIOE, GPIO_PinSource11, GPIO_AF_FSMC);
 GPIO_PinAFConfig(GPIOE, GPIO_PinSource12, GPIO_AF_FSMC);
 GPIO_PinAFConfig(GPIOE, GPIO_PinSource13, GPIO_AF_FSMC);
 GPIO_PinAFConfig(GPIOE, GPIO_PinSource14, GPIO_AF_FSMC);
 GPIO_PinAFConfig(GPIOE, GPIO_PinSource15, GPIO_AF_FSMC);
 GPIO_Init(GPIOE, &GPIO_InitStructure);

 /* External memory OE (#4 for reading from flash) and WE (#5 for writing to flash) */
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
 GPIO_PinAFConfig(GPIOD, GPIO_PinSource4, GPIO_AF_FSMC);
 GPIO_PinAFConfig(GPIOD, GPIO_PinSource5, GPIO_AF_FSMC);
 GPIO_Init(GPIOD, &GPIO_InitStructure);

 /* External memory CS2 (for selecting the flash part to interact) */
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
 GPIO_PinAFConfig(GPIOG, GPIO_PinSource9, GPIO_AF_FSMC);
 GPIO_Init(GPIOG, &GPIO_InitStructure);

 // NADV pin
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
 GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_FSMC);
 GPIO_Init(GPIOB, &GPIO_InitStructure);

 /* External memory WAIT (to get status from the flash part) */
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 GPIO_Init(GPIOD, &GPIO_InitStructure);

 /*-- FSMC Configuration ----------------------------------------------------*/
 p.FSMC_AddressSetupTime = 0x0f;   // 0 to 15 (table 215 p1529) <= 2 or NADV won't pulse
 p.FSMC_AddressHoldTime = 0x04;   // 1 to 15 (table 215 p1529)
 p.FSMC_DataSetupTime = 0x2f;   // 1 to 256 (table 215 p1529) <= 5 gives last write; seq otherwise
 p.FSMC_BusTurnAroundDuration = 0x01; // 0 to 15 (table 215 p1529)
 p.FSMC_CLKDivision = 0x00;    // don't care (p.1548)
 p.FSMC_DataLatency = 0x00;    // don't care (p.1548)
 p.FSMC_AccessMode = 0x00;    // don't care (p.1560) only used during EXTMOD

 // configured according to p1547
 FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM2;
 FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;      // disable or 0
 FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable;   // if if memory supports it; otherwise 0
 FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;     // disable or 0
 FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;      // disable or 0
 FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;     // as needed?
 FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState; // don't care
 FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;       // disable or 0
 FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;   // meaningful only if AsynchronousWait is 1
 FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;    // disable or 0
 FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;     // as needed
 FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_NOR;       // 0x2 (NOR Flash memory)
 FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Enable;     // enable or 1
 FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &p;
 FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &p;

 FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);

 /*!< Enable FSMC Bank1_NOR Bank */
 FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM2, ENABLE);
}

void ExtFlash_Verify(void)
{
    //  Issue the Software Product ID code to SST39VF401C
    *sysAddress(0x555) = 0x00AA;  // write data 0x00AA to device addr 0x555
    *sysAddress(0x2AA) = 0x0055;  // write data 0x0055 to device addr 0x2AA
    *sysAddress(0x555) = 0x0090;  // write data 0x0090 to device addr 0x555

    Delay_150_Nano_Seconds();

    // Read the product ID from SST39VF401C
    mfr_id  = *sysAddress(0x0000);   // get first ID byte
    dev_id  = *sysAddress(0x0001);   // get second ID byte

    // Issue the Software Product ID Exit code, thus returning the
    // SST39VF401C to the normal operation.
    *sysAddress(0x555) = 0x00AA;  // write data 0x00AA to device addr 0x555
    *sysAddress(0x2AA) = 0x0055;  // write data 0x0055 to device addr 0x2AA
    *sysAddress(0x555) = 0x00F0;  // write data 0x00F0 to device addr 0x555
 
    Delay_150_Nano_Seconds();
}

Outcomes