刚接触stm32,参考的f429的例程修改的nand flash用的是MT29F8G16ADADA的芯片,就是对例程引脚配置进行修改,读id始终不成功,有人能帮看看是什么问题吗?
nand.c
nand_attriute nand_dev; //nand重要参数结构体
//初始化NAND FLASH
u8 NAND_Init(void)
{
GPIO_InitTypeDef GPIO_Initure;
FSMC_NANDInitTypeDef NAND_Handler; //NAND FLASH句柄
FSMC_NAND_PCCARDTimingInitTypeDef ComSpaceTiming,AttSpaceTiming;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD|RCC_AHB1Periph_GPIOE|RCC_AHB1Periph_GPIOG, ENABLE);//使能PD,PE,PF,PG时钟
RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FSMC,ENABLE);//使能FSMC时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,ENABLE);
GPIO_Initure.GPIO_Pin = (3<<0)|(3<<4)|(0XF<<7)|(7<<10)|(3<<14);
GPIO_Initure.GPIO_Mode = GPIO_Mode_AF;//复用输出
GPIO_Initure.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_Initure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_Initure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOD, &GPIO_Initure);//初始化
GPIO_Initure.GPIO_Pin = (0X1F<<7)|(0XF<<12);
GPIO_Initure.GPIO_Mode = GPIO_Mode_AF;//复用输出
GPIO_Initure.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_Initure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_Initure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOE, &GPIO_Initure);//初始化
GPIO_Initure.GPIO_Pin = GPIO_Pin_6;
GPIO_Initure.GPIO_Mode = GPIO_Mode_AF;//复用输出
GPIO_Initure.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_Initure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_Initure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOG, &GPIO_Initure);//初始化
GPIO_PinAFConfig(GPIOD,GPIO_PinSource0,GPIO_AF_FSMC);//PD0,AF12
GPIO_PinAFConfig(GPIOD,GPIO_PinSource1,GPIO_AF_FSMC);//PD1,AF12
GPIO_PinAFConfig(GPIOD,GPIO_PinSource4,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource5,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource7,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource8,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource9,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource10,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource11,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource12,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource14,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource15,GPIO_AF_FSMC);//PD15,AF12
GPIO_PinAFConfig(GPIOE,GPIO_PinSource7,GPIO_AF_FSMC);//PE7,AF12
GPIO_PinAFConfig(GPIOE,GPIO_PinSource8,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource9,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource10,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource11,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource12,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource13,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource14,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource15,GPIO_AF_FSMC);//PE15,AF12
GPIO_PinAFConfig(GPIOG,GPIO_PinSource6,GPIO_AF_FSMC);
ComSpaceTiming.FSMC_SetupTime=2; //建立时间
ComSpaceTiming.FSMC_WaitSetupTime=3; //等待时间
ComSpaceTiming.FSMC_HoldSetupTime=2; //保持时间
ComSpaceTiming.FSMC_HiZSetupTime=1; //高阻态时间
AttSpaceTiming.FSMC_SetupTime=2; //建立时间
AttSpaceTiming.FSMC_WaitSetupTime=3; //等待时间
AttSpaceTiming.FSMC_HoldSetupTime=2; //保持时间
AttSpaceTiming.FSMC_HiZSetupTime=1; //高阻态时间
// NAND_Handler.Instance=FMC_NAND_DEVICE;
//NAND_Handler.Init.NandBank=FMC_NAND_BANK3; //NAND挂在BANK3上
NAND_Handler.FSMC_Bank=FSMC_Bank2_NAND; //NAND挂在BANK2上
NAND_Handler.FSMC_Waitfeature=FSMC_Waitfeature_Disable; //关闭等待特性
NAND_Handler.FSMC_MemoryDataWidth=FSMC_MemoryDataWidth_16b; //16位数据宽度
NAND_Handler.FSMC_ECC=FSMC_ECC_Disable; //不使用ECC
NAND_Handler.FSMC_ECCPageSize=FSMC_ECCPageSize_512Bytes; //ECC页大小为2K
NAND_Handler.FSMC_TCLRSetupTime=0; //设置TCLR(tCLR=CLE到RE的延时)=(TCLR+TSET+2)*THCLK,THCLK=1/180M=5.5ns
NAND_Handler.FSMC_TARSetupTime=1; //设置TAR(tAR=ALE到RE的延时)=(TAR+TSET+2)*THCLK,THCLK=1/180M=5.5n。
NAND_Handler.FSMC_CommonSpaceTimingStruct=&ComSpaceTiming;
NAND_Handler.FSMC_AttributeSpaceTimingStruct=&AttSpaceTiming;
// HAL_NAND_Init(&NAND_Handler,&ComSpaceTiming,&AttSpaceTiming);
FSMC_NANDInit(&NAND_Handler);
FSMC_NANDCmd(FSMC_Bank2_NAND,ENABLE);
NAND_Reset(); //复位NAND
delay_ms(100);
nand_dev.id=NAND_ReadID(); //读取ID
NAND_ModeSet(4); //设置为MODE4,高速模式
if(nand_dev.id==MT29F16G08ABABA) //NAND为MT29F16G08ABABA
{
nand_dev.page_totalsize=4320; //nand一个page的总大小(包括spare区)
nand_dev.page_mainsize=4096; //nand一个page的有效数据区大小
nand_dev.page_sparesize=224; //nand一个page的spare区大小
nand_dev.block_pagenum=128; //nand一个block所包含的page数目
nand_dev.plane_blocknum=2048; //nand一个plane所包含的block数目
nand_dev.block_totalnum=4096; //nand的总block数目
}
else if(nand_dev.id==MT29F4G08ABADA)//NAND为MT29F4G08ABADA
{
nand_dev.page_totalsize=2112; //nand一个page的总大小(包括spare区)
nand_dev.page_mainsize=2048; //nand一个page的有效数据区大小
nand_dev.page_sparesize=64; //nand一个page的spare区大小
nand_dev.block_pagenum=64; //nand一个block所包含的page数目
nand_dev.plane_blocknum=2048; //nand一个plane所包含的block数目
nand_dev.block_totalnum=4096; //nand的总block数目
}
else if(nand_dev.id==MT29F8G16ADADA)//NAND为MT29F8G16ADADA
{
nand_dev.page_totalsize=2112; //nand一个page的总大小(包括spare区)
nand_dev.page_mainsize=2048; //nand一个page的有效数据区大小
nand_dev.page_sparesize=64; //nand一个page的spare区大小
nand_dev.block_pagenum=64; //nand一个block所包含的page数目
nand_dev.plane_blocknum=2048; //nand一个plane所包含的block数目
nand_dev.block_totalnum=8192; //nand的总block数目
}else return 1; //错误,返回
return 0;
}
//读取NAND FLASH的ID
//返回值:0,成功;
// 其他,失败
u8 NAND_ModeSet(u8 mode)
{
*(vu8*)(NAND_ADDRESS|NAND_CMD)=NAND_FEATURE;//发送设置特性命令
*(vu8*)(NAND_ADDRESS|NAND_ADDR)=0X01; //地址为0X01,设置mode
*(vu8*)NAND_ADDRESS=mode; //P1参数,设置mode
*(vu8*)NAND_ADDRESS=0;
*(vu8*)NAND_ADDRESS=0;
*(vu8*)NAND_ADDRESS=0;
if(NAND_WaitForReady()==NSTA_READY)return 0;//成功
else return 1; //失败
}
//读取NAND FLASH的ID
//不同的NAND略有不同,请根据自己所使用的NAND FALSH数据手册来编写函数
//返回值:NAND FLASH的ID值
u32 NAND_ReadID(void)
{
u8 deviceid[5];
u32 id;
u32 data = 0;
*(vu8*)(NAND_ADDRESS|NAND_CMD)=NAND_READID; //发送读取ID命令
*(vu8*)(NAND_ADDRESS|NAND_ADDR)=0X00;
//ID一共有5个字节
data = *(vu32 *)(NAND_ADDRESS | DATA_AREA);
deviceid[0]=*(vu8*)NAND_ADDRESS;
deviceid[1]=*(vu8*)NAND_ADDRESS;
deviceid[2]=*(vu8*)NAND_ADDRESS;
deviceid[3]=*(vu8*)NAND_ADDRESS;
deviceid[4]=*(vu8*)NAND_ADDRESS;
//镁光的NAND FLASH的ID一共5个字节,但是为了方便我们只取4个字节组成一个32位的ID值
//根据NAND FLASH的数据手册,只要是镁光的NAND FLASH,那么一个字节ID的第一个字节都是0X2C
//所以我们就可以抛弃这个0X2C,只取后面四字节的ID值。
id=((u32)deviceid[1])<<24|((u32)deviceid[2])<<16|((u32)deviceid[3])<<8|deviceid[4];
//deviceid[1] = ADDR_1st_CYCLE (data);
// deviceid[2] = ADDR_2nd_CYCLE (data);
// deviceid[3] = ADDR_3rd_CYCLE (data);
// deviceid[4] = ADDR_4th_CYCLE (data);
//id=((u32)deviceid[1])|((u32)deviceid[2])|((u32)deviceid[3])|deviceid[4];
return id;
}
//读NAND状态
//返回值:NAND状态值
//bit0:0,成功;1,错误(编程/擦除/READ)
//bit6:0,Busy;1,Ready
u8 NAND_ReadStatus(void)
{
vu8 data=0;
*(vu8*)(NAND_ADDRESS|NAND_CMD)=NAND_READSTA;//发送读状态命令
data++;data++;data++;data++;data++; //加延时,防止-O2优化,导致的错误.
data=*(vu8*)NAND_ADDRESS; //读取状态值
return data;
}
//等待NAND准备好
//返回值:NSTA_TIMEOUT 等待超时了
// NSTA_READY 已经准备好
u8 NAND_WaitForReady(void)
{
u8 status=0;
vu32 time=0;
while(1) //等待ready
{
status=NAND_ReadStatus(); //获取状态值
if(status&NSTA_READY)break;
time++;
if(time>=0X1FFFF)return NSTA_TIMEOUT;//超时
}
return NSTA_READY;//准备好
}
//复位NAND
//返回值:0,成功;
// 其他,失败
u8 NAND_Reset(void)
{
*(vu8*)(NAND_ADDRESS|NAND_CMD)=NAND_RESET; //复位NAND
if(NAND_WaitForReady()==NSTA_READY)return 0;//复位成功
else return 1; //复位失败
} |