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数据端口的最后状态

}



友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
5条回答
shuaigew88
1楼-- · 2019-07-20 15:43
问题解决了,最后没办法用了逻辑分析仪将NAND_FLASH总线时序抓出来进行分析,总算是找出问题并得以解决。
jcxxkj
2楼-- · 2019-07-20 16:05
shuaigew88 发表于 2016-9-17 20:17
问题解决了,最后没办法用了逻辑分析仪将NAND_FLASH总线时序抓出来进行分析,总算是找出问题并得以解决。

楼主是不是地址发送的不对啊,分享一下问题所在啊!!
shuaigew88
3楼-- · 2019-07-20 17:37
 精彩回答 2  元偷偷看……
SR_LI
4楼-- · 2019-07-20 21:25
可否分享下代码
shuaigew88
5楼-- · 2019-07-21 01:19
SR_LI 发表于 2017-5-11 09:50
可否分享下代码

这个欲等待处理我实际是将NANDFLASH的片选信号单独用软件控制实现的,我实际FSMC硬件是旁路了片选信号,因为没搞懂STM32的欲等待机制也懒得搞。实际使用时只要注意就没影响,这个方法同样适用于FSMC片选信号不够的场合。

一周热门 更多>