技术开发 频道

自己动手编写嵌入式Bootloader---基本功能流程

  2. nand读操作

  在编译连接时,我们把上述 start.S 代码放在生成的二进制映像文件的最开始位置,因而也被烧写到 Nand Flash 的最起始位置,因而会被自动拷贝到 SteppingStone 里运行。start.S 要完成的任务之一,是把S-Boot的所有代码从Nand Flash拷贝到内存中,这里需要对NAND的读操作,因此对NAND的初始化和读操作要在第一阶段写好。

  以开发板上使用的K9F1208为例,每个页(page)为512Byte数据和16Byte校验,每个块(Block)为32个页,即16KByte数据和512Byte校验。

  Nand Flash只用8根线与CPU的DATA0-7连接,位宽为8位,不管是数据、地址或控制字都通过这8根线传递,如果读写数据的话每次只能传输一个字节数据。Nand Flash的操作通过NFCONF、NFCMD、NFADDR、NFDATA、NFSTAT和NFECC六个寄存器来完成。在S3C2440A数据手册第218页可以看到读写Nand Flash的操作时序:1. 通过NFCONF寄存器配置Nand Flash;2.写Nand Flash命令到NFCMD寄存器;3.写Nand Flash地址到 NFADDR寄存器;4. 在读写数据时,通过NFSTAT寄存器获得Nand Flash的状态信息。应该在读操作前或写操作后检查R/nB信号(Ready/Busy信号)。

  初始化NAND Flash:S3C2440的NFCONF寄存器用来设置时序参数TACLS、TWRPH0、TWRPH1,设置数据位宽;还有一些只读位。TACLS、 TWRPH0、TWRPH1这三个参数控制的是Nand Flash信号线CLE/ALE与写控制信号nWE的时序关系。

  注意,寄存器值转换成实际的时钟周期值时,TACLS不需加1,而TWRPH0和TWRPH1需要加1。比如NFCONF寄存器中设置 TACLS=1,TWRPH0=3,TWRPH1=0,意思是时序图中 TACLS=1个HCLK时钟,TWRPH0=4个HCLK时钟,TWRPH1=1个HCLK时钟。

void nand_init(void)
{
    
//时间参数设为:TACLS=0 TWRPH0=3 TWRPH1=0
    NFCONF = 0x300;
    
/* 使能NAND Flash控制器, 初始化ECC, 禁止片选 */
    NFCONT
= (1<<4)|(1<<1)|(1<<0);
    
/* 复位NAND Flash */
    NFCONT
&= ~(1<<1); //发出片选信号
    NFCMMD = 0xFF; //复位命令
    s3c2440_wait_idle();//循环查询NFSTAT位0,直到它等于1
    NFCONT |= 0x2; //取消片选信号
}

   读操作:读操作也是以页(512Byte)为单位进行的。在初始上电时,器件进入缺省的“读方式1模式”。在这一模式下,页读操作通过将0x00写入指令寄存器,接着写入3个地址(1个列地址和2个行地址)来启动。一旦页读指令被器件锁存,下面的页读操作就不需要再重复写入页读指令了。写入页读指令和地址后,处理器可以通过对信号线R//B的分析来判断页读操作是否完成。如果信号为低电平,表示器件正忙;如果信号为高电平,表示器件内部操作完成,要读取的数据被送入了数据寄存器。外部控制器可以再以50ns为周期的连续/RE脉冲信号的控制下,从IO口依次读出数据。连续页读操作中,输出的数据是从指定的列地址开始,直到该页最后一个列地址的数据为止。

for(i=start_addr; i < (start_addr + size);)
     {
         NFCMMD
= 0; //发出READ0命令
         s3c2440_write_addr(i); //Write Address
         s3c2440_wait_idle(); //循环查询NFSTAT位0,直到它等于1
         for(j=0; j < NAND_SECTOR_SIZE; j++, i++)
         {
            
*buf = (unsigned char)NFDATA;
             buf
++;
         }
     }

  缺点:没有使用ECC校验和纠错;没有使用坏块检查;

 

0
相关文章