lpcware

EMC with Spansion S29GL064N90BFI030

Discussion created by lpcware Employee on Jun 15, 2016
Latest reply on Jun 18, 2016 by lpcware
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);
}   

Outcomes