当前位置: 首页 > Linux

魏东山一期视频学习笔记-Nandflash

时间:2023-04-06 23:48:25 Linux

硬件原理分析引脚功能CLE高电平ALE低电平传输命令CLE低电平ALE高电平传输地址ALE与CLE低电平传输数据CLE片选信号低电平有效,因为LDATA信号为多个芯片共用的RnB状态管脚,高电平表示空闲,低电平表示忙见WE上升沿通知nand写数据,RE下降沿后延时tREA输出数据,比较命令列表直接操作和nandcontroller操作之间,使用uboot体验nand操作uboot安装参考上一篇魏东山第一期视频学习笔记-Norflash####阅读ID1。SelectthechipNFCONT(0X4E000004)bit1set1选择芯片,md.l4E0000041读出寄存器值(因为是32bit寄存器),可以看到没有选择芯片,mw.l4E0000041使能闪存2。发出命令0x90NFCMMD(0X4E000008)写入0x90,mw.b4E00000890(b写入1字节)3.发出地址0x00NFADDR(0X4E00000C)写入0x00,mw.b4E00000C00(b写入1字节)4.读取数据ReadNFDATA(0X4E000010)ubootcommandmd.b4E00001015.ReadDeviceCodeReadNFDATA(0X4E000010)ubootcommandmd.b4E0000101可以看到读取到的数据与芯片手册一致6.退出读取ID状态Reset命令mw.b4E000008ffread0addresscontent使用uboot命令nanddump0查看nand中数据读取操作的时序发出以下命令读取0地址testmw.l4E0000041//enablenandflashmw.b4E00000800//Issuecommandmw.b4E00000C00//发出地址mw.b4E00000C00//发出地址mw.b4E00000C00//发出地址mw.b4E00000C00//发出地址md.b4E0000101//读取数据mw.b4E000008ff//reset命令可以看到运行结果与uboot命令直接读取nandflash的结果一致K9F1208U0MNandflash存储结构分析(64M)1page是528bytes(512bytes+16bytesoob)1block有32pagesCPU访问Nand地址不会访问oob部分,对于CPU来说是不存在的,一个page只有512Byteoob的存在是为了解决nand数据容易出错的问题K9F1208U0MNandflash时序分析2440Nand控制器时序K9F1208U0M芯片时序从图中可以看出从CLE/ALE信号发送到WE信号发送TACLS的延时可以设置为0,WE有效时间TWRPH0最小25ns,TWRPH1最小10nsnandflash控制器初始化配置NFCONF寄存器初始化后,HCLK配置为100M(10ns),根据上面分析时序寄存器配置为#defineTACLS0//1-clk(0ns)#defineTWRPH06//3-clk(25ns)#defineTWRPH10//1-clk(10ns)//TACLS+TWRPH0+TWRPH1>=50nsNFCONF=(TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)|(0<<0);NFCONT寄存器配置使能NAND闪存控制器,暂时关闭片选,打开ECCNFCONT=(0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(0<<6)|(0<<5)|(1<<4)|(1<<1)|(1<<0);nandflashIDRead//读取IDvoidNand_Read_ID(){unsignedcharbuf[4];Nand_Select();Nand_CMD(0x90);Nand_Addr_Byte(0x00);buf[0]=Nand_Data();buf[1]=Nand_Data();buf[2]=Nand_Data();buf[3]=Nand_Data();Nand_Deselect();printf("字节1=0x%x\n\r",buf[0]);printf("字节2=0x%x\n\r",buf[1]);printf("字节3=0x%x\n\r",buf[2]);printf("Byte4=0x%x\n\r",buf[3]);}注意头文件寄存器的定义NFDATA需要指向unsignedchar*type#define__REG_BYTE(x)(*(volatileunsignedchar*)(x))#defineNFDATA__REG_BYTE(0x4E000010)//NANDflash数据生成的bin文件为11kb,需要烧写到norflash才能运行这里读取nandflash数据的地址信号只有对于目前的64Mflash先发送列地址,再发送页地址。列地址分为256字节的上半区和256字节的下半区。如果列地址起始地址为0~255,使用00命令,列地址起始地址为256~511使用01命令//readflash//参数;读取地址读取存储数组读取长度voidNand_Read(unsignedintaddr,unsignedchar*buf,unsignedintlen){inti=0;整页,列;Nand_Select();while(i=0&&col<=255){Nand_CMD(0x00);//上半区读取命令}elseif(col>=256&&col<=511){Nand_CMD(0x01);//下半区读取命令col=col-256;}Nand_Addr_Byte(col&0xff);Nand_Addr_Byte(page&0xff);Nand_Addr_Byte((页面>>8)&0xff);Nand_Addr_Byte((page>>16)&0xff);Nand_Wait_Ready();//续读for(;(col<256)&&(i>8)&0xff);Nand_Addr_Byte((page>>16)&0xff);Nand_CMD(0xD0);_Wait_Ready();//读取状态位Nand_CMD(0x70);status=Nand_Data();printf("状态=0x%x\n\r",状态);len=len-(16*1024);//减去1个块的长度if(len==0)break;addr=addr+(16*1024);//指向下一个块}Nand_Deselect();return0;}nandflash写因为列地址只能在A0~A7之间寻址,所以写的起始地址只能在页的前256字节,//writeflash//parameter;写地址写数组长度intNand_Write(unsignedintaddr,unsignedchar*buf,unsignedintlen){inti=0;整页,列;printf("addr=0x%x;buf=%s;len=%d\n\r",addr,buf,len);col=addr%PAGE_SIZE;if(col>255){printf("起始地址大于255\n\r");返回-1;}Nand_Select();while(1){page=addr/PAGE_SIZE;//第一页col=addr%PAGE_SIZE;//第一列printf("page=%d;col=%d\n\r",page,col);Nand_CMD(0x80);//发送地址Nand_Addr_Byte(col&0xff);Nand_Addr_Byte(page&0xff);Nand_Addr_Byte((页面>>8)&0xff);Nand_Addr_Byte((page>>16)&0xff);//连续写入数据for(;(colSDRAMcopyfunctionvoidNand_Copy_to_SDRAM(unsignedintsource_addr,unsignedchar*dst_addr,intlen){unsignedcharbuf[64];诠释我;整数索引=0;while(1){Nand_Read(来源e_addr,缓冲区,64);for(i=0;i<64;i++){*dst_addr=buf[i];dst_addr++;源地址++;索引++;}if(index>len)中断;}}完整代码https://github.com/olichlika/...