EMC with Spansion S29GL064N90BFI030

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

EMC with Spansion S29GL064N90BFI030

310 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Alonix on Thu Mar 03 08:35:36 MST 2016
Hi everyone,
I'm trying to interface a Spansion NOR S29GL064N90BFI030 Flash using the EMC of the LPC1788 controller on a custom board. You find the schematic as attachment. The controller is already interfaceing an external SRAM properly. For the NOR Flash test project the SRAM is excluded. My code is based on the KEIL flashing algorithm template for this flash memory. The communication is controlled by CS1 at address 0x9000000. At the moment I'm not even able to read the devideID of the flash.

I have searched through the internet already. I also checked this forum:
[list]
  [*]https://www.lpcware.com/content/forum/lpc1788-nor-flash-s29gl128p
  [*]https://www.lpcware.com/content/forum/spansion-emc-nor-flash-lpc1788
[/list]

The EMC is running with 60MHz at the moment. These are my settings

const EmcStaticMemoryConfig extProgFlash = 
{   
    .memWidth = EMC_MEM_WIDTH_16,
    .pageMode = EMC_MEM_PAGE_MODE_DISABLE,
    .chipSel = EMC_MEM_CHIP_SEL_ACT_LOW, 
    .laneState = EMC_MEM_BYTE_LANE_STATE_HALF_WORD_WITH,
    .extWait = EMC_MEM_EXTENDED_WAIT_DISABLE, 
    .buffer = EMC_MEM_BUFFER_DISABLE,
    .wrProt = EMC_MEM_WRITE_NOT_PROTECTED,
    .extWaitSum = 0,
    .chan = 1,
    .writeEnableDelay = 0x3,   //StaticWaitWen       (n + 1) * EMCCLK              
    .readEnableDelay = 0x3,    //StaticWaitOen       n * EMCCLK
    .writeDataDelay = 0xA,  //StaticWaitWr        (n + 2) * EMCCLK
    .readDataDelay = 0x5,   //StaticWaitRd        (n + 1) * EMCCLK
    .pageModeDelay = 0x8,   //StaticWaitPage      (n + 1) * EMCCLK
    .waitTurnDelay = 0x7,   //StaticWaitTurn      (n + 1) * EMCCLK
};


The EMC Config results in the EMC register contents
[list]
  [*]STATICCONFIG1 0x81
  [*]CONTROL   1
  [*]CONFIG 0
  [*]EXTENDENDEDWAIT 0
  [*]Timings like in the struct
  [*]
[/list]

I checked if
- all pins are configured to EMC function
- The EMC is enabled in the PCONP
- Output changes of the chip select line with the Oscilloscope
- The SYSCON SCS EMCSC bit is set to 1
- The emc clock prescaler of the CPU Clock is set to 1
- The periperal is enabled EMC->Controll  = 1

At the moment I'm totally out of clue what's going wrong. Does anyone have an idea?
Many thanks,
Jonny

The following code is used to read the flash device ID

#define M32(adr) (*((volatile unsigned long  *) (adr)))
#define base_adr 0x90000000

void EMC_NOR_ReadID(unsigned short* manId)
{
    M32(base_adr + (0x555 << 2)) = 0x00AA00AA;
    M32(base_adr + (0x2AA << 2)) = 0x00550055;
    M32(base_adr + (0x555 << 2)) = 0x00900090;

    *manId = *(volatile short *)base_adr;
}

Here you find my EMC configuration.

//###################### P U B L I C   F U N C T I O N S ####################### 

void initEMC(void)
{
    //Power up lcd peripheral
    CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCEMC, true);

    configureEMCPins();
    
    //Disable all dynamic memory features
    LPC_EMC->DynamicControl = 0;
    
    LPC_EMC->Control = 0; //Disable peripheral
        
    //Set little endian format
    LPC_EMC->Config = 0;    
        
    //Use half clock as CPU 60 MHz
    LPC_SC->EMCCLKSEL = 1;

    //Disable automatic address shifting
    //LPC_SC->SCS |=  (1 << 0);

    configureEMCForStaticMemory(&extProgFlash);
   
    LPC_EMC->Control |= 1; //Enable the EMC 
    
    for(volatile uint32_t i = 0; i < 99999; i++) {}



}

//##################### P R I V A T E   F U N C T I O N S ###################### 

static void configureEMCForStaticMemory(const EmcStaticMemoryConfig* conf)
{
    //Set Extende wait  time out
    //0x0 = 16 clock cycles.
    //0x1 - 0x3FF = (n+1) x16 clock cycles.    
    if(conf->extWait == EMC_MEM_EXTENDED_WAIT_ENABLE)
        LPC_EMC->StaticExtendedWait = 0;    
     
    *statMemChanReg[conf->chan].StaticConfig = conf->memWidth;
    *statMemChanReg[conf->chan].StaticConfig |= conf->pageMode;
    *statMemChanReg[conf->chan].StaticConfig |= conf->chipSel;
    *statMemChanReg[conf->chan].StaticConfig |= conf->laneState;
    *statMemChanReg[conf->chan].StaticConfig |= conf->extWait;
    *statMemChanReg[conf->chan].StaticConfig |= conf->buffer;
    *statMemChanReg[conf->chan].StaticConfig |= conf->wrProt;
    
    //Write enable delay: chip select -> write enable.
    //0x0 = One EMCCLK cycle delay between assertion of chip select and we
    //0x1 - 0xF = (n + 1) * EMCCLK cycle delay.
    *statMemChanReg[conf->chan].StaticWaitWen = conf->writeEnableDelay;

    //Output enable delay: chip select or address change, whichever is later,
    //                     to the output enable.    
    //0x0 = No delay (POR reset value).
    //0x1 - 0xF = n cycle delay. The delay is WAITOEN x tEMCCLK.    
    *statMemChanReg[conf->chan].StaticWaitOen = conf->readEnableDelay;
    
    //Read delay: chip select -> read access
    //first read only: 0x0 - 0x1E = (n + 1) * EMCCLK cycles for read accesses.
    //For non-sequential reads, the wait state time is (WAITRD + 1) x tEMCCLK.
    //0x1F = 32 EMCCLK cycles for read accesses.
    *statMemChanReg[conf->chan].StaticWaitRd = conf->readDataDelay;
    
    //Page Mode ready delay:
    //0x0 - 0x1E = (n + 1) * EMCCLK cycle read access time
    //0x1F = 32 EMCCLK cycle read access time.
    *statMemChanReg[conf->chan].StaticWaitPage = conf->pageModeDelay;
    
    //Write delay:  chip select -> write access
    //0x0 - 0x1E = (n + 2) * EMCCLK cycle write access time.
    //0x1F = 33 EMCCLK cycle write access time.
    *statMemChanReg[conf->chan].StaticWaitWr = conf->writeDataDelay; 
    
    ////Turn round delay: number of bus turnaround cycles
    //0x0 - 0xE = (n + 1) * EMCCLK turn-around cycles.
    //0xF = 16 EMCCLK turn-around cycles.
    *statMemChanReg[conf->chan].StaticWaitTurn = conf->waitTurnDelay;
}

static void configureEMCPins(void)
{
    //OE
    PINSEL_ConfigPin(4, 24, 1);
    
    //WE
    PINSEL_ConfigPin(4, 25, 1);
    
    //BLE
    PINSEL_ConfigPin(4, 26, 1);
    
    //BHE
    PINSEL_ConfigPin(4, 27, 1);
    
    //CS0
    PINSEL_ConfigPin(4, 30, 1);
    
    //CS1
    PINSEL_ConfigPin(4, 31, 1);
    
    //D0_15
    for(uint8_t dataPin = 0; dataPin < 16; dataPin ++)
        PINSEL_ConfigPin(3, dataPin, 1);
    
    //A0_21
    for(uint8_t addrPin = 0; addrPin < 23; addrPin ++)
        PINSEL_ConfigPin(4, addrPin, 1);
}    
Labels (1)
0 Kudos
2 Replies

240 Views
lpcware
NXP Employee
NXP Employee
bump
0 Kudos

240 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by gjswalling on Wed Mar 09 22:36:52 MST 2016
Your code appears to be for 2x16 interleaved flash (two 16-bit chips for 32-bit data bus), but the schematic shows just a single chip.  I think the schematic looks correct for connecting a single chip, but in that case, I would expect to shift the offset only one bit, not two.  Just to verify the commands are reaching the flash pins correctly, can you capture with a logic analyzer to verify?  Another item to check is power up timing.  Please refer to tVCS and tRH on page 64 of the data sheet:
http://www.cypress.com/file/202426/download

Best Regards,
Gary Swalling
0 Kudos