Tiny6410 的NandFlash(K9GAG08U0E)
来源:互联网 发布:淘宝暴利行业排行榜 编辑:程序博客网 时间:2024/05/17 08:57
tiny6410的nand flash学的我实在是揪心,这个问题的引出主要是我读取内核并启动没有成功,2440的nand flash是2K读取,但我在查看Nand Flash的数据手册时,发现这块flash的page是8K每页,所以在我写的bootloader中来自己更改代码,而不是跟友善保持一致(以2K读),一开始以的是8K每页读,才发现前4页为2K,但当以前4页2K读,后面8K读(当然这里是我的错误认知),然后基于这样的一个考虑后,我发现以2K每页读取NandFlash,代码运行成功,我以8K每页读取NandFlash,代码运行一样成功,问题就在这里,如果这样考虑,代码到底是每页多少被写到NandFlash的?事实证明的是,这篇文章给了我答案,看来还真是。
以下文章转载自:
Tiny6410+K9GAG08U0E http://blog.csdn.net/o0Avalon0o/article/details/49644553
友善采用这颗8K Page的Nand,在6410上面搭配使用,确实给用户添加了不少麻烦,再加上ecc部分使用软件实现,代码不开源,学到块驱动的时候确实揪心啊~~
内部SRAM的大小
先从启动说起,Tiny6410启动选用的是用户手册里面屏蔽掉的一种直接Nand启动方式,如下图,根据友善原理图的OM[4:0]电平,对应表中的RESERVED,这种启动方式就是上电后直接将Nand的前面一部分代码映射到片内SRAM中,开始启动。
而三星官方推荐的启动方式应该是从IROM中启动,然后通过IROM将NAND中的代码拷贝到片内SRAM,再跳转到SRAM中启动。
这里看了网上很多资料,有的人说SRAM是8K,有的说是4K,这里我看到用户手册里面是说有4K,但是我用Tiny6410调试裸板程序的时候,发现确实是拷贝了8K代码:
这里自己有个猜测:对于友善使用的这种隐藏的启动方式,就是直接将代码放到SRAM空间运行,此时当然就有8K RAM空间了;但是当使用三星推荐的从IROM中运行,那么IROM中运行的代码的临时变量都是保存在SRAM上面的,所以可能是官方想保留上半4K RAM用于IROM启动。
8K页大小问题
从上面启动选择那张图片可以看到,其实上6410最大仅支持4K页,并不支持8K页,而对于友善使用的被保留启动方式更是最多支持large page(2K)。
所以在开始的8K SRAM代码拷贝中需要注意,系统只会拷贝每个8K页中的前2K数据,而友善配套提供的superboot升级程序在烧写U-boot镜像的时候都只是操作每页中前2K空间。
而对应的在U-Boot源码中也可以看到拷贝U-boot到SDRAM中运行的函数,仅操作了前2K数据:
static int nandll_read_blocks (ulong dst_addr, ulong size, int large_block){ uchar *buf = (uchar *)dst_addr; int i; uint page_shift = 9; if (large_block) page_shift = 11; /* Read pages */ for (i = 0; i < (0x3c000>>page_shift); i++, buf+=(1<<page_shift)) { nandll_read_page(buf, i, large_block); } return 0;}
可以看到在整个启动到U-boot代码搬运过程中,都没有启动ecc,所以在这个过程中数据都是不可靠的,而在友善的论坛里面也看到过他们承认,有掉U-boot固件的可能性。这也不能全怪人家,硬件决定6410拷贝8K代码的时候已经不安全了,那么后面Uboot重定向的时候做不做ecc都不是太重要了。。。
在进入U-boot第二阶段start_armboot中之后,通过调用nand_scan()跟友善不开源的NAND_Init(),从这里之后即对K9GAG08U0E完成初始化,开启软件ECC,此后对Kernel、Rootfs的数据操作都是变为可靠了。
这里再吐槽一下,调用NAND_Init()竟然会改变U-Boot的环境变量,搞的我每次通过mini6410.h文件设置的环境变量都无效,这也是醉了。。。P.S.经过验证,友善应该是在Nand上面开辟了一段空间用于保存环境变量,调用NAND_Init之后,系统将直接从Nand的这段地址中还原环境参数,也就是说修改/include/configs/mini6410.h下面的环境变量屁用都没有,对于一块全新的开发板只要在Uboot中调用一次setenv、saveenv,保存到Nand中,下次如果仅更新Uboot固件时,则不需要再重新设置环境变量了(确保你用的Uboot是最新版,旧版本Uboot命令行下不支持saveenv保存参数)。
推荐解决方法可以在NAND_Init()后面使用void setenv (char *varname, char *varvalue)重新设置。
Tiny6410中的nand命令
友善提供的最新U-Boot终于支持对K9GAG08U0E进行写入操作了,分析cmd_nand.c中的do_nand():
/* read write */ if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) { int read; if (argc < 4) goto usage; addr = (ulong)simple_strtoul(argv[2], NULL, 16); read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */ printf("\nNAND %s: ", read ? "read" : "write"); if (arg_off_size(argc - 3, argv + 3, nand, &off, &size) != 0) return 1; s = strchr(cmd, '.'); if (s != NULL && (!strcmp(s, ".jffs2") || !strcmp(s, ".e") || !strcmp(s, ".i"))) { if (read) { ret = FriendlyARMReadNand( (u_char*)addr, size, off); if (ret == -1) { puts("offset should be multiple of page size\n"); } } else { /* write */ nand_write_options_t opts; memset(&opts, 0, sizeof(opts)); opts.buffer = (u_char*) addr; opts.length = size; opts.offset = off; /* opts.forcejffs2 = 1; */ opts.pad = 1; opts.blockalign = 1; opts.quiet = quiet; if (NandIsMlc()) { ret = -1; puts("write.jffs2/write.e/write.i is not supported\n"); } else ret = nand_write_opts(nand, &opts); }#ifdef CFG_NAND_YAFFS_WRITE } else if (!read && s != NULL && + (!strcmp(s, ".yaffs") || !strcmp(s, ".yaffs1"))) { nand_write_options_t opts; memset(&opts, 0, sizeof(opts)); opts.buffer = (u_char*) addr; opts.length = size; opts.offset = off; opts.pad = 0; opts.blockalign = 1; opts.quiet = quiet; opts.writeoob = 1; opts.autoplace = 1; /* jsgood */ /* if (s[6] == '1') opts.forceyaffs = 1; */ ret = nand_write_opts(nand, &opts);#endif } else { if (read) { if (!NandIsMlc()) { ret = nand_read(nand, off, &size, (u_char *)addr); } else { ret = FriendlyARMReadNand( (u_char*)addr, size, off); if (ret == -1) { puts("offset should be multiple of page size\n"); } } } else { if (NandIsMlc()) { if (off % NandBlockSizeInByte != 0) { puts("offset should be multiple of block size\n"); ret = -1; } else { unsigned int i; ret = 0; for (i = 0; i < size; i += NandBlockSizeInByte) { int len = size - i; if (len > NandBlockSizeInByte) { len = NandBlockSizeInByte; } FriendlyARMWriteNand(((u_char *)addr) + i, len, off + i, NandBlockSizeInByte); } } } else { ret = nand_write(nand, off, &size, (u_char *)addr); if (ret == 0) { uint *magic = (uint*)(PHYS_SDRAM_1); if ((0x24564236 == magic[0]) && (0x20764316 == magic[1])) magic[0] = 0x27051956; } } } }
从代码可以看到,只有nand read.i == nand read可以完成K9GAG08U0E的读操作,且它们都要求操作地址必须是page对齐;
而nand write可以完成K9GAG08U0E的写操作,同样,操作地址需要page对齐(8K),且暂时还不支持带oob数据的文件系统镜像的烧写(yaffs)!!
- Tiny6410 的NandFlash(K9GAG08U0E)
- Tiny6410+K9GAG08U0E
- tiny6410 nandflash驱动设计
- s3c6410 开发板Linux系统支持 K9GAG08U0E的方法(第一篇)
- s3c6410 开发板Linux系统支持 K9GAG08U0E的方法(第二篇)
- s3c6410 开发板Linux系统支持 K9GAG08U0E的方法
- 【原创】Tiny6410用SD卡烧写LInux到Nandflash
- Tiny6410 的内核移植(拿来主义)
- 基于Nios的nandFlash控制(一)
- 基于Nios的nandFlash控制(二)
- 基于Nios的nandFlash控制(三)
- 3.mini2440的nandflash读写(裸机)
- Linux MTD层的研究(Nandflash)
- 移植ads7846驱动到tiny6410(tiny6410)
- 移植ads7846驱动到tiny6410(tiny6410)
- Tiny6410 lcd的移植
- tiny6410 uboot的移植
- tiny6410的yaffs2文件系统的制作及其安装(1)
- ADAMS shortcut
- BAT机器学习面试题及解析(256-260题)
- Mysql -SOUNDEX()函数
- 设计模式学习笔记(四)抽象工厂模式
- 基于OpenCV的视频图像组态 (8) :随机线条动画效果
- Tiny6410 的NandFlash(K9GAG08U0E)
- DecaWave产品简略总结
- 第十五周项目一(3)——验证算法之直接选择排序
- iOS开发UI篇—Quartz2D复杂图形绘制(三) 图片文字,进度条,饼形图,小黄人
- 初探Laravel框架中的源码(一)
- 高德地图(一)之简单集成
- Android studio提示Android studio 在gradle文件中引入support:appcompat-v7:22.2.0包的时候出现Failed to resolve的错误
- 获取在CS-money上某件物品价格波动的图表
- 人工智能的伦理问题