lpcware

NOR Flash Init on LPC1778

Discussion created by lpcware Employee on Jun 15, 2016
Latest reply on Jun 15, 2016 by lpcware
Content originally posted in LPCWare by arion2001 on Wed Feb 04 02:50:54 MST 2015
Hi,

I am using LPC1778, 12 MHz. I am trying to initialize my Flash on chip select  0 to work even after following all the procedures mentioned in the LPC1778 manual, but to no avail. The compiler I am using is Crossworks Rowley 2.2.
Note: Although the schematic label the NOR Flash as Spansion part, I am using a MACRONIX NOR FLASH as per attached on the spec.
Attached is the image of how my Flash is connected. I am trying to access the Autoselect mode to read out manufacturer id and device id but to no avail.
Below is the code I use to init this guy.



//EMC_OEN Shared
//P2[24]
#define OEN_SEL               LPC_IOCON->P2_24 |= 0x31

//EMC_WEN Shared
//P4[25]
#define WEN_SEL                   LPC_IOCON->P4_25 |= 0x31
//Nor_Flash /CS0 pin4[30]
#define NORFLASH_CS0_SELLPC_IOCON->P4_30 |= 0x31

//Nor_Flash /CS1 pin4[31]
#define NORFLASH_CS1_SELLPC_IOCON->P4_31 |= 0x31

//Nor_Flash RY/BY pin0[4]
//Ready Busy indicates running in progress. At High Z = ready, at Vil = actively erasing/programming
#define NORFLASH_RYBY_SEL      LPC_IOCON->P0_4   |= 0x218
#define NORFLASH_RYBY_IN       LPC_GPIO4->DIR &= ~(0x10)
#define NORFLASH_RYBY_BIT      LPC_GPIO4->PIN &    0x10

static void pinConfig_EMC(void) {
//Select slew rate and also config for EMC use = 0x31 , with pullup
LPC_IOCON->P3_0 |= 0x31; /* D0 @ P3.0 */
LPC_IOCON->P3_1 |= 0x31; /* D1 @ P3.1 */
LPC_IOCON->P3_2 |= 0x31; /* D2 @ P3.2 */
LPC_IOCON->P3_3 |= 0x31; /* D3 @ P3.3 */

LPC_IOCON->P3_4 |= 0x31; /* D4 @ P3.4 */
LPC_IOCON->P3_5 |= 0x31; /* D5 @ P3.5 */
LPC_IOCON->P3_6 |= 0x31; /* D6 @ P3.6 */
LPC_IOCON->P3_7 |= 0x31; /* D7 @ P3.7 */

LPC_IOCON->P3_8 |= 0x31; /* D8 @ P3.8 */
LPC_IOCON->P3_9 |= 0x31; /* D9 @ P3.9 */
LPC_IOCON->P3_10 |= 0x31; /* D10 @ P3.10 */
LPC_IOCON->P3_11 |= 0x31; /* D11 @ P3.11 */

LPC_IOCON->P3_12 |= 0x31; /* D12 @ P3.12 */
LPC_IOCON->P3_13 |= 0x31; /* D13 @ P3.13 */
LPC_IOCON->P3_14 |= 0x31; /* D14 @ P3.14 */
LPC_IOCON->P3_15 |= 0x31; /* D15 @ P3.15 */ //also  A-1 LSB address input in byte mode

LPC_IOCON->P4_1 |= 0x31; /* A1 @ P4.1 */
LPC_IOCON->P4_2 |= 0x31; /* A2 @ P4.2 */
LPC_IOCON->P4_3 |= 0x31; /* A3 @ P4.3 */

LPC_IOCON->P4_4 |= 0x31; /* A4 @ P4.4 */
LPC_IOCON->P4_5 |= 0x31; /* A5 @ P4.5 */
LPC_IOCON->P4_6 |= 0x31; /* A6 @ P4.6 */
LPC_IOCON->P4_7 |= 0x31; /* A7 @ P4.7 */

LPC_IOCON->P4_8 |= 0x31; /* A8 @ P4.8 */
LPC_IOCON->P4_9 |= 0x31; /* A9 @ P4.9 */
LPC_IOCON->P4_10 |= 0x31; /* A10 @ P4.10 */
LPC_IOCON->P4_11 |= 0x31; /* A11 @ P4.11 */

LPC_IOCON->P4_13 |= 0x31; /* A13 @ P4.13 */
LPC_IOCON->P4_14 |= 0x31; /* A14 @ P4.14 */
LPC_IOCON->P4_15 |= 0x31; /* A15 @ P4.15 */
LPC_IOCON->P4_16 |= 0x31; /* A16 @ P4.16 */

LPC_IOCON->P4_17 |= 0x31; /* A17 @ P4.17 */
LPC_IOCON->P4_18 |= 0x31; /* A18 @ P4.18 */
LPC_IOCON->P4_19 |= 0x31; /* A19 @ P4.19 */
LPC_IOCON->P4_20 |= 0x31; /* A20 @ P4.20 */

LPC_IOCON->P4_21 |= 0x31; /* A21 @ P4.21 */
LPC_IOCON->P4_22 |= 0x31; /* A22 @ P4.22 */
LPC_IOCON->P4_23 |= 0x31; /* A23 @ P4.23 */
LPC_IOCON->P5_0  |= 0x31; /* A24 @ P5.0 */
LPC_IOCON->P5_1  |= 0x31; /* A25 @ P5.1 */

NORFLASH_CS0_SEL;
NORFLASH_CS1_SEL;
NORFLASH_RYBY_SEL;

OEN_SEL;
WEN_SEL; 

}


void NORFLASH_Init(void)
{
  pinConfig_EMC();
  NORFLASH_RYBY_SEL;
  NORFLASH_RYBY_IN;
  LPC_SC->PCONP = 0x00000800;
  LPC_SC->EMCCLKSEL = 0x00000001;  //divide CPU clock by half
  //LPC_SC->EMCCLKSEL = 0x00000000;
 
  LPC_SC->EMCDLYCTL = 0X0a05;
  LPC_EMC->Config   = 0x00000000;  //little endian
  LPC_EMC->Control  &= ~(BIT2_EN+BIT1_EN+BIT0_EN);  //Turn off EMC first for configuration
 
  LPC_EMC->StaticConfig0    = 0x81;//16bit,page mode disable,active low CS,byte lane disable,
                                   //extended wait disable,buffer disable, no write protect
 

  LPC_EMC->StaticWaitWen0   = 0x00000002;            //WaitWen0+1 Delay from CHip Select to Write Enable
  LPC_EMC->StaticWaitOen0   = 0x00000001;            // Chip Select to output enable or address change whichever is later
  LPC_EMC->StaticWaitRd0    = 0x00000010;            //Chip select to read access
  LPC_EMC->StaticWaitPage0  = 0x0000001F;            //Delay for asynchronous page mode sequential accesses for EMC_CS0.
  LPC_EMC->StaticWaitWr0    = 0x00000010;            // program the delay from the chip select to the write access 
  LPC_EMC->StaticWaitTurn0  = 0x0000000F;            //Number of bus turnaround cycles EMC_CS0.

  LPC_EMC->Control         |= 0x00000001;
 
}




Below is how I did my autoselect. My question would be is there any way I could verify if my command went in successfully? The manufacturer ID I got was 0000h. Which is incorrect, the correct value should be C2h and the device Id I got were 0xffff which is again not correct. Been at it for sometime but I still unable to figure out what is wrong here.


void Flash_Read(void)
{
  /* Here is an example of Autoselect mode (getting manufacturer ID) */
  /* Define UINT16 example: typedef unsigned short UINT16; */
  //<MemorySegment size="0x70000" access="ReadOnly" start="0x00000000" name="FLASH"/> Internal Flash
  //volatile u_int8_t *bit_shifted_in = <some memory address>; 
  volatile uint32_t *base_addr = 0x80000000; 
  unsigned long manuf_id = 0; 
  unsigned long device_id_1 = 0;
  unsigned long device_id_2 = 0;
  unsigned long device_id_3 = 0; 
  /* Auto Select Entry */ 
  *( base_addr + 0x555 ) = 0x00AA; /* write unlock cycle 1 */
  *( base_addr + 0x2AA ) = 0x0055; /* write unlock cycle 2 */      
  *( base_addr + 0x555 ) = 0x0090; /* write autoselect command */   
  /* multiple reads can be performed after entry */ 
  manuf_id    = *( base_addr + 0x000 ); /* read manuf. id */
  device_id_1 = *( base_addr + 0x001 );
  device_id_2 = *( base_addr + 0x00E );
  device_id_3 = *( base_addr + 0x00F );
 
  /* Autoselect exit */
  *( (uint16_t *)base_addr + 0x000 ) = 0x00F0; /* exit autoselect (write reset command) */

}

Outcomes