STM32F4操作NANDFLASH问题

2019-07-20 14:23发布

本帖最后由 shuaigew88 于 2016-9-17 20:25 编辑

    我用STM32F407的FSMC驱动NANDFLASH(K9F1208)可以正常读出NANDFLASH的ID,现在的问题是当正确擦除块后用页读命令读取擦除的块时读出的数据全是0,
void NAND_GpioInit()
{
  GPIO_InitTypeDef myGPIO;
  AFGPIO_InitTypeDef myAFGPIO;

  myGPIO.GPIO_Pin =GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_14|GPIO_Pin_15;  
  myGPIO.GPIO_Mode =GPIO_Mode_AF;
  myGPIO.GPIO_OType =GPIO_OType_PP;
  myGPIO.GPIO_PuPd =GPIO_PuPd_NOPULL;
  myGPIO.GPIO_Speed =GPIO_Speed_100MHz;
  GPIO_Init(GPIOD,&myGPIO);

  myGPIO.GPIO_Pin =GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10;  
  GPIO_Init(GPIOE,&myGPIO);

  myGPIO.GPIO_Pin =GPIO_Pin_9;  
  GPIO_Init(GPIOG,&myGPIO);


  myGPIO.GPIO_Pin =GPIO_Pin_6;  
  myGPIO.GPIO_Mode =GPIO_Mode_IN;
  myGPIO.GPIO_PuPd =GPIO_PuPd_IPU;
  myGPIO.GPIO_OType =GPIO_OType_OD;
  GPIO_Init(GPIOG,&myGPIO);
  myGPIO.GPIO_Pin =GPIO_Pin_6;  
  GPIO_Init(GPIOD,&myGPIO);


  myAFGPIO.GPIO_Pin =AFGPIO_Pin_0|AFGPIO_Pin_1|AFGPIO_Pin_4|AFGPIO_Pin_5|AFGPIO_Pin_11|AFGPIO_Pin_12|AFGPIO_Pin_14|AFGPIO_Pin_15;
  myAFGPIO.GPIO_AF =AFGPIO_AF12;
  AFGPIO_Init(GPIOD,&myAFGPIO);

  myAFGPIO.GPIO_Pin =AFGPIO_Pin_7|AFGPIO_Pin_8|AFGPIO_Pin_9|AFGPIO_Pin_10;
  AFGPIO_Init(GPIOE,&myAFGPIO);

  myAFGPIO.GPIO_Pin =AFGPIO_Pin_9;
  AFGPIO_Init(GPIOG,&myAFGPIO);
}

void NAND_FsmcInit()
{
  FSMC_Bank3 ->PCR3 =0;
  FSMC_Bank3 ->PCR3|=(UINT32)(1<<13);  //ALE To RE Delay
  FSMC_Bank3 ->PCR3|=(UINT32)(1<<9);   //CLE To RE Delay

  //FSMC_Bank3 ->PCR3|=(1<<1); //en wait
  //FSMC_Bank3 ->PCR3|=(1<<17); //ecc 512
  //FSMC_Bank3 ->PCR3|=(1<<6); //en ecc

  FSMC_Bank3 ->PMEM3 =0;
  FSMC_Bank3 ->PMEM3|=(UINT32)(1<<24);  //Mem HiZ Hold =1
  FSMC_Bank3 ->PMEM3|=(UINT32)(2<<16);  //Mem Hold time  =2
  FSMC_Bank3 ->PMEM3|=(UINT32)(3<<8);   //Mem Wait time =3
  FSMC_Bank3 ->PMEM3|=(UINT32)(1<<0);   //Mem Setup time =1


  FSMC_Bank3 ->PATT3 =0;
  FSMC_Bank3 ->PATT3|=(UINT32)(1<<24);
  FSMC_Bank3 ->PATT3|=(UINT32)(2<<16);
  FSMC_Bank3 ->PATT3|=(UINT32)(3<<8);
  FSMC_Bank3 ->PATT3|=(UINT32)(1<<0);


  FSMC_Bank3 ->PCR3|=(UINT32)(1<<3);   //NANDFLASH
  FSMC_Bank3 ->PCR3|=(UINT32)(1<<2);   //NANDFLASH Enable

  NAND_GpioInit();
// NAND_Reset();
}


void NAND_Reset()
{
  NAND_WrCmd(0xff);
  NAND_Busy();
}

UINT32 NAND_ReadID()
{
  UINT32 id =0;
  NAND_WrCmd(0x90);
  NAND_WrAdr(0x00);
  id =NAND_RdByte() <<24;

  NAND_WrAdr(0x01);
  id|=NAND_RdByte() <<16;

  NAND_WrAdr(0x02);
  id|=NAND_RdByte() <<8;

  NAND_WrAdr(0x03);
  id|=NAND_RdByte() <<0;
  return id;
}

UINT8 NAND_ReadSR()
{
  static UINT8 sr=0;
  NAND_WrCmd(0x70);
  NAND_Busy();

  sr =NAND_RdByte();
  return sr;
}

UINT8 NAND_BlockErase(UINT32 bladr)
{
  bladr <<=5;   
  NAND_WrCmd(0x60);
  NAND_WrAdr(bladr);
  NAND_WrAdr(bladr>>8);
  NAND_WrAdr(bladr>>16);
  NAND_WrCmd(0xD0);
  NAND_Busy();

  if((NAND_ReadSR()&0x01) !=NAND_OK)return NAND_FAIL;
  return NAND_OK;
}

void NAND_PageRead(UINT32 padr,UINT8 *Buf)
{
  UINT16 i;
  NAND_WrCmd(0x00);           
  NAND_WrAdr(0);
  NAND_WrAdr(padr);
  NAND_WrAdr(padr>>8);
  NAND_WrAdr(padr>>16);
  NAND_Busy();

  for(i=0;i<512;i++)Buf=NAND_RdByte();
}

UINT8 NAND_PageWrite(UINT32 padr,UINT8 *Buf)
{
  UINT16 i;
  NAND_WrCmd(0x80);           
  NAND_WrAdr(0);
  NAND_WrAdr(padr);
  NAND_WrAdr(padr>>8);
  NAND_WrAdr(padr>>16);

  Delay_ms(1);
  for(i=0;i<512;i++)NAND_WrByte(Buf);
  NAND_WrCmd(0x10);
  NAND_Busy();

  if((NAND_ReadSR()&0x01)!=NAND_OK)return NAND_FAIL;
  return NAND_OK;
}



//include
#define NAND_OK   0
#define NAND_FAIL 1

#define CMD_AREA          ((UINT32)0x010000)  /* A16 = CLE  high */   
#define ADDR_AREA         ((UINT32)0x020000)  /* A17 = ALE high */     
#define DATA_AREA         ((UINT32)0x000000)
#define Bank_NAND_ADDR    ((UINT32)0x80000000)


#define NAND_WrCmd(Cmd)          (*(UINT8 *)(Bank_NAND_ADDR | CMD_AREA)) =Cmd
#define NAND_WrAdr(Adr)   (*(UINT8 *)(Bank_NAND_ADDR | ADDR_AREA)) =Adr
#define NAND_WrByte(Dat)  (*(UINT8 *)(Bank_NAND_ADDR | DATA_AREA)) =Dat
#define NAND_RdByte()     (*(UINT8 *)(Bank_NAND_ADDR | DATA_AREA))

#define NAND_Busy()  while((GPIOG ->IDR & (1<<6))==0)




//main函数
NAND_FsmcInit();
tmp =NAND_ReadID();  //可以正常读出ID号


res =NAND_BlockErase(0); //块擦除返回OK
NAND_PageRead(0,buf);  //读出擦除的数据全是0,读取数据错误

目前可以确定是FSMC配置问题,因为我用IO模拟时序的时候读写NANDFLASH块的数据都是正确的,IO模拟时将下面4个宏改成4个函数,分别写了IO模拟时序。
#define NAND_WrCmd(Cmd)          (*(UINT8 *)(Bank_NAND_ADDR | CMD_AREA)) =Cmd
#define NAND_WrAdr(Adr)   (*(UINT8 *)(Bank_NAND_ADDR | ADDR_AREA)) =Adr
#define NAND_WrByte(Dat)  (*(UINT8 *)(Bank_NAND_ADDR | DATA_AREA)) =Dat
#define NAND_RdByte()     (*(UINT8 *)(Bank_NAND_ADDR | DATA_AREA))


用下面的IO模拟时序时数据是正确的,所以可以肯定是FSMC配置的问题,但我实在是找不出问题来。
UINT8 NAND_RdByte()
{
  UINT8 tmp;
  NAND_GPIO_OUT(0xff);
  NAND_CLE_CLR();
  NAND_ALE_CLR();
  NAND_CS_CLR();
  Delay_us(100);

  NAND_RE_CLR();
  Delay_us(200);
  tmp =NAND_GPIO_IN();
  NAND_RE_SET();
  Delay_us(100);

  NAND_CLE_SET();
  NAND_ALE_SET();
  NAND_CS_SET();
  return tmp;
}

void NAND_WrByte(UINT8 Dat)
{
  NAND_CLE_CLR();
  NAND_ALE_CLR();

  NAND_CS_CLR();
  NAND_GPIO_OUT(Dat);
  Delay_us(500);

  NAND_WE_CLR();
  Delay_us(100);
  NAND_WE_SET();
  Delay_us(100);

  NAND_CLE_SET();
  NAND_ALE_SET();
  NAND_CS_SET();
}

void NAND_WrCmd(UINT8 Cmd)
{
  NAND_ALE_CLR();

  NAND_CS_CLR();
  NAND_GPIO_OUT(Cmd);
  Delay_us(500);

  NAND_WE_CLR();
  Delay_us(100);
  NAND_WE_SET();
  Delay_us(100);

  NAND_ALE_SET();
  NAND_CS_SET();
}

void NAND_WrAdr(UINT8 Adr)
{
  NAND_CLE_CLR();

  NAND_CS_CLR();
  NAND_GPIO_OUT(Adr);
  Delay_us(500);

  NAND_WE_CLR();
  Delay_us(100);
  NAND_WE_SET();
  Delay_us(100);

  NAND_CLE_SET();
  NAND_CS_SET();
}


麻烦大虾们帮我看看配置时序哪里有问题,可以正常读出ID,然后就是页读函数
void NAND_PageRead(UINT32 padr,UINT8 *Buf)
{
  UINT16 i;
  NAND_WrCmd(0x00);           
  NAND_WrAdr(0);
  NAND_WrAdr(padr);
  NAND_WrAdr(padr>>8);
  NAND_WrAdr(padr>>16);
  NAND_Busy();  
  
  for(i=0;i<512;i++)Buf=NAND_RdByte(); //我发现当运行到这里的时候NAND的数据总线是处于高阻态的,NANDFLASH没有数据返回,读取的数据是GPIO数据端口的最后状态

}



友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。