lpcware

need help getting S34ML04G2 NAND flash to work with lpc1788

Discussion created by lpcware Employee on Jun 15, 2016
Latest reply on Jun 15, 2016 by lpcware
Content originally posted in LPCWare by shoeloader on Mon Nov 10 06:56:59 MST 2014
I have a custom board with a lpc1788 with IS42S16400F SDRAM and S34ML04G200TF100 NAND flash.
I got the SDRAM to work but the flash won't initialize.
I use the code for the embedded artist oem board. The difference is that the embedded artist board uses the K9F1G08U0C chip and that I don't use buffers.
The command for requesting an id is 0x90 in both chips
When I request the ID of the chip it returns only 1's.

Here's how the flash is connected:
[list]
  [*]IO0 to IO7 connected to EMC_D0 to EMC_D7(same as oem1788)
  [*]nRE connected to EMC_OE (same as oem1788)
  [*]CLE connected to EMC_A20(same as oem1788)
  [*]ALE connected to EMC_A19(same as oem1788)
  [*]nCE connected to EMC_CS1 + 10k pull-up(same as oem1788)
  [*]nWE connected to EMC_WE(same as oem1788)
  [*]nWP connected to 3v3(same as oem1788)
  [*]nR/B connected to EMC_A23 + 10k pull-up (is not connected on oem1788 )
[/list]

Here is part of my code:


#define K9F1G_CLE   ((volatile uint8_t *)0x90100000)//1<<20
#define K9F1G_ALE   ((volatile uint8_t *)0x90080000)//1<<19
#define K9F1G_DATA  ((volatile uint8_t *)0x90000000)
       
#define K9FXX_READ_ID           0x90

static void pinConfig(void)
{
  LPC_IOCON->P3_0 |= 1; //D0 @ P3.0
  LPC_IOCON->P3_1 |= 1; //D1 @ P3.1
  LPC_IOCON->P3_2 |= 1; //D2 @ P3.2
  LPC_IOCON->P3_3 |= 1; //D3 @ P3.3

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

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

  LPC_IOCON->P3_12 |= 1; //D12 @ P3.12
  LPC_IOCON->P3_13 |= 1; //D13 @ P3.13
  LPC_IOCON->P3_14 |= 1; //D14 @ P3.14
  LPC_IOCON->P3_15 |= 1; //D15 @ P3.15

  LPC_IOCON->P3_16 |= 1; //D16 @ P3.16
  LPC_IOCON->P3_17 |= 1; //D17 @ P3.17
  LPC_IOCON->P3_18 |= 1; //D18 @ P3.18
  LPC_IOCON->P3_19 |= 1; //D19 @ P3.19

  LPC_IOCON->P3_20 |= 1; //D20 @ P3.20
  LPC_IOCON->P3_21 |= 1; //D21 @ P3.21
  LPC_IOCON->P3_22 |= 1; //D22 @ P3.22
  LPC_IOCON->P3_23 |= 1; //D23 @ P3.23

  LPC_IOCON->P3_24 |= 1; //D24 @ P3.24
  LPC_IOCON->P3_25 |= 1; //D25 @ P3.25
  LPC_IOCON->P3_26 |= 1; //D26 @ P3.26
  LPC_IOCON->P3_27 |= 1; //D27 @ P3.27

  LPC_IOCON->P3_28 |= 1; //D28 @ P3.28
  LPC_IOCON->P3_29 |= 1; //D29 @ P3.29
  LPC_IOCON->P3_30 |= 1; //D30 @ P3.30
  LPC_IOCON->P3_31 |= 1; //D31 @ P3.31
 

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

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

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

  LPC_IOCON->P4_12 |= 1; //A12 @ P4.12
  LPC_IOCON->P4_13 |= 1; //A13 @ P4.13
  LPC_IOCON->P4_14 |= 1; //A14 @ P4.14
  LPC_IOCON->P4_15 |= 1; //A15 @ P4.15

  LPC_IOCON->P4_16 |= 1; //A16 @ P4.16
  LPC_IOCON->P4_17 |= 1; //A17 @ P4.17
  LPC_IOCON->P4_18 |= 1; //A18 @ P4.18  
 
 
  LPC_IOCON->P4_19 |= 1; //A19 @ P4.19

  LPC_IOCON->P4_20 |= 1; //A20 @ P4.20
 
 
  LPC_IOCON->P4_21 |= 1; //A21 @ P4.21
  LPC_IOCON->P4_22 |= 1; //A22 @ P4.22
 
  LPC_IOCON->P4_23 |= 1; //A23 @ P4.23
 
 
  LPC_IOCON->P4_24 |= 1; //OEN @ P4.24
  LPC_IOCON->P4_25 |= 1; //WEN @ P4.25
  LPC_IOCON->P4_26 |= 1; //BLSN[0] @ P4.26
  LPC_IOCON->P4_27 |= 1; //BLSN[1] @ P4.27

  LPC_IOCON->P4_28 |= 1; //BLSN[2] @ P4.28
  LPC_IOCON->P4_29 |= 1; //BLSN[3] @ P4.29
  LPC_IOCON->P4_30 |= 1; //CSN[0] @ P4.30
  LPC_IOCON->P4_31 |= 1; //CSN[1] @ P4.31

  LPC_IOCON->P2_14 |= 1; //CSN[2] @ P2.14
  LPC_IOCON->P2_15 |= 1; //CSN[3] @ P2.15
}

static uint64_t nandReadId(void)
{
  uint8_t a, b, c, d, e;
  volatile uint8_t *pCLE;
  volatile uint8_t *pALE;
  volatile uint8_t *pData;
 
  pCLE  = K9F1G_CLE;
  pALE  = K9F1G_ALE;
  pData = K9F1G_DATA;
   
  *pCLE = K9FXX_READ_ID;
  *pALE = 0;
   
  a = *pData;
  b = *pData;
  c = *pData;
  d = *pData;
  e = *pData;
 
   
  return ((uint64_t)a << 32) | (b << 24) | (c << 16) | (d << 8) | e;
}

bool nand_init (void)
{
  volatile uint64_t nandId = 0;
  TIM_TIMERCFG_Type timerCfg;

  LPC_SC->PCONP     |= 0x00000800;
  LPC_EMC->Control   = 0x00000001;//enable
  LPC_EMC->Config    = 0x00000000;//little endian

  pinConfig();

  TIM_ConfigStructInit(TIM_TIMER_MODE, &timerCfg);
  TIM_Init(LPC_TIM0, TIM_TIMER_MODE, &timerCfg);

  LPC_EMC->StaticConfig1   = 0x00000080;//Byte lane state.

 
  LPC_EMC->StaticWaitWen1  = 0x00000002;
  LPC_EMC->StaticWaitOen1  = 0x00000002;
  LPC_EMC->StaticWaitRd1   = 0x00000008;
  LPC_EMC->StaticWaitPage1 = 0x0000001f;
  LPC_EMC->StaticWaitWr1   = 0x00000008;
  LPC_EMC->StaticWaitTurn1 = 0x0000000f;
 
  nandId = nandReadId();//returns 0xFF FFFF FFFF
 
  if( nandId != 0x01CC90D556ULL ){
    return false;
  }
 

/*
  if ((nandId & 0xffff0000) !=
    (((uint32_t)(ID_MARKER_CODE) << 24) | ID_SAMSUNG << 16)) {
    // unknown NAND chip
    return false;
  }
*/

  pageSize   = 1024 * (1 << (nandId & 0x03)); 
  blockSize  = 64*1024 * (1 << ((nandId>>4) & 0x03));
  reduntSize = 8 * (1 << ((nandId >> 1) & 0x1));

                        
  return true;
}


What am I doing wrong?

Outcomes