gnu ucos 加入nandflash 操作并支持nand启动
? ? ? ? nandflash 因为造价低在对大容量的数据存储中发挥着重要的作用。nandflash没有地址或数据总线,如果是8位 nandflash(我见过的最多的情况),那么它只有8个IO口还有一些控制口,控制口在不同状态切换这8个IO口分别用于传输命令、地址和数据。nandflash主要以page(页)为单位进行读写,以block(块)为单位进行擦除。Nand Flash芯片每一位只能从1写为0,而不能从0写为1,所以在对其进行写入操作之前一定要将相应块擦除(擦除就是将相应块的位全部变为1) ? ? ? ?s3c2440处理器集成了 nandflash 控制器,还有一个特殊的功能:在系统刚上电之后不依赖于任何代码 把nandflash前4K的内容搬运到“Steppingstone”的内部SRAM缓存。 然后把该Steppingstone映射为Bank0,最后从这4K代码开始执行。这个功能很有用,可以把系统最必要的初始化代码和搬运的代码放到这4K当中--4K已经够多了,记得以前 看《自己动手写操作系》那个bios只是把512字节的东西搬运到内存中。搬运代码就负责把剩余的代码从nandflash中搬运到ram中,然后跳转到ram中去执行主要的程序! 这里使用的是mini2440上的K9F1G08,跟赵春江老师的K9F2G08U0A 几乎无多大差别。 这里的1G代表1Gbit 也就是128Mbyte。关于nandflash命名规则可见如下链接:blog.sina.com.cn/s/blog_604c12520100tqil.html K9F2G08U0A的一页为(2K+64)字节(加号前面的2K表示的是main区容量,加号后面的64表示的是spare区容量),它的一块为64页,而整个设备包括了2048个块。这样算下来一共有2112M位容量,如果只算main区容量则有256M字节(即256M×8位)。 ? ? 要实现用8个IO口来要访问这么大的容量,K9F2G08U0A规定了用5个周期来实现。第一个周期访问的地址为A0~A7;第二个周期访问的地址为A8~A11,它作用在IO0~IO3上,而此时IO4~IO7必须为低电平;第三个周期访问的地址为A12~A19;第四个周期访问的地址为A20~A27;第五个周期访问的地址为A28,它作用在IO0上,而此时IO1~IO7必须为低电平。前两个周期传输的是列地址,后三个周期传输的是行地址。通过分析可知,列地址是用于寻址页内空间,行地址用于寻址页,如果要直接访问块,则需要从地址A18开始。 下面重点介绍下如何实现从nandflash中启动。 /* * we do sys-critical inits only at reboot,* not when booting from ram! */ adr r0,_start /* r0 <- current position of code */ cmp r0,#0x0 /* don't reloc during debug */ blne cpu_init_crit bl memsetup /* we run from nandflash*/ @ copy ucos to RAM mov r0,#0x0 ldr r1,=TEST_RAM mov r2,#0x100000 @ get read to call C functions (for copy2ram) ldr sp,DW_STACK_START @ setup stack pointer bl copy2ram cpu_init_crit: mov r1,#GPIO_CTL_BASE add r1,r1,#oGPIO_F? ?这里的adr是相对寻址,也就是从相对于当前 pc 的位置得到标号_start的位置,可见如下链接: blog.csdn.net/sukhoi27smk/article/details/8876201 上面前3条指令反汇编形式是: 300000c0: e24f00c8 sub r0,pc,#200 ; 0xc8 300000c4: e3500000 cmp r0,#0 300000c8: 1b000005 blne 300000e4 <cpu_init_crit>如果是从jtag仿真器 启动那么 _start 被放在0x30000000 位置处r0与0不等,跳转到cpu_init_crit执行。? 如果是被烧写到nandflash中并被2440加载到前4K 那么得到的r0寄存器值也就是0。 接下来就执行memsetup 和 copy2ram 。 然后就是copy2ram : 整个 nandflash 拷贝操作代码是从 u-boot 里面拷贝出来的,直接上代码没必要讲解 。值得注意一点就是函数 nand_read_ll 有一个如下的循环: for(i=start_addr; i < (start_addr + size);) { /* ·¢3?READ0?üá? */ write_cmd(0); /* Write Address */ write_addr_lp(i); write_cmd(0x30); wait_idle(); for(j=0; j < NAND_SECTOR_SIZE_LP; j++,i++) { *buf = read_data(); buf++; } }? ? ?如果程序用最高优化等级编译,那么编译器会把上面循环优化的,像 write_cmd ?read_data 之类的都会拿到循环外面来,这是肯定不对的。 所以对于这种函数要禁止编译器优化需要在函数前面加个声明: void __attribute__((optimize("O0"))) nand_read_ll(unsigned char *buf,unsigned long start_addr,int size) 还有其它一些函数也需要 禁止优化。 关于优化的可见下面文章: http://forum.andestech.com/viewtopic.php?f=16&t=225 ? ?最后就是 跳转到主程序开始执行了,注意这里要是绝对跳转指令才行(因为这条跳转指令有可能在前4K中,也有可能在0x30000000 以后的某个地址处)! ldr pc,__main __main: .word main @bl main @ call main b . 反汇编形式如下: 30000104: e51ff004 ldr pc,[pc,#-4] ; 30000108 <__main> 30000108 <__main>: 30000108: 300005c4 andcc r0,r0,r4,asr #11 3000010c: eafffffe b 3000010c <__main+0x4> 看到了正好跳转到 0x300005c4 ,也就是main函数起始地址。 前面的函数 copy2ram 把前4K的内容也拷贝到了 0x30000000 位置处,这里的跳转跳转到了 0x300005c4 。
blog.csdn.net/ustc_dylan/article/details/6965330 ? ? ? ? 示例代码中在Task0 里面有个函数关于nandflash验证的代码如下: void nand_test() { UINT8 buff[2048]; int i; for(i = 0;i < 2048;i ++) buff[i] = i & 0xff; nand_init_ll(); printf("erase result is %xrn",nand_eraseblock(8)); printf("write result is %xrn",nand_writepage(515,buff,2048)); for(i = 0;i < 2048;i ++) buff[i] = 0x0; printf("read result is %xrn",nand_read_3(515 * 2048,2048)); for(i = 0;i < 4;i ++){ printf("%2x ",buff[i]); } nand_ramdom_write(514,2048 - 33,0xf4); printf("result is :%x rn",nand_ramdom_read(514,2048 - 33)); nand_readID(buff); printf("nand ID is :"); for(i = 0;i < 5;i ++) printf("%x ",buff[i]); printf("rn"); } 上面功能依次是? ? ? ? ?擦除一块nandflash ? ? ? ?向擦除的flash 某个页写一页数据,读出来刚才写的数据;? ? ? ? ?nand随机写然后再随机读刚才写的数值 ? ? ? ?读出nandflash的ID ? ? ? ?另外还有一个大小端的问题,arm架构支持大小端模式切换,但默认的是小端模式; nandflash 是8位的, 字访问,半字访问,字节访问 读出来字节序列不一样的!! 为了加快速度,一般都选择字访问! 当 nand_readpage 调用函数接口是 nand_read_page 当按照字节读的时候:
nandflash操作很多控制细节 都是是参考?zhaocj 的讲解来的,这里就不多废话了。参考链接: blog.csdn.net/zhaocj/article/details/5803699 可以去我的github clone 完整的代码。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |