在上一篇中我们重点介绍了K9GAG08U0D 和 K9GAG08U0E的区别,除了这些外还有一个需要重点关注的地方,下面我们详细讲解。

Uboot从NandFlash启动第一步就是把NandFlash的前8K代码拷贝到s3c6410内部的SRAM中,然后运行,这8K的代码会从NandFlash中把完整的Uboot代码拷贝到6410开发板片外内存中,我这里使用的是256M的DDR,Uboot的存放地址为0x5FE00000,虚拟地址为 0xCFE00000.

注意:关键的8K代码不是在U0D(每页4K)的前两页存放,也不是在U0E(每页8K)的第一页存放,而是在U0E或者U0D的             前四页中存放的,前四页分为每页2K,总共8K,这是由s3c6410芯片本身所规定的。这8K字节外后面的数据就是按实             际的页数存放了,U0D 每页存放4K字节,U0E每页存放8K字节。

s3c6410支持从SD卡启动,从SD卡启动后就可以把Uboot.bin文件写入NandFlash了,可以认真的看一下Uboot 里面 的 nand write.uboot 命令是如何把数据写入NandFlash前4页 的。写入成功后就可以从NandFlash启动Uboot。

nand write.uboot 的关键代码 位于uboot1.1.6/common/cmd_nand.c文件中:

if (!read && s != NULL && (!strcmp(s, ".uboot")) && nand->writesize == 4096) //U0D

{

size=4096;
            nand_write(nand, off, &size, (u_char *)addr);
            off+=4096;
            addr+=2048;
           nand_write(nand, off, &size, (u_char *)addr);
            off+=4096;
            addr+=2048;
           nand_write(nand, off, &size, (u_char *)addr);
           off+=4096;
           addr+=2048;
           nand_write(nand, off, &size, (u_char *)addr);
           off+=4096;
           addr+=2048;

size=1024*1024-4*4096;
            ret = nand_write(nand, off, &size, (u_char *)addr);

}else if(!read && s != NULL && (!strcmp(s, ".uboot")) && nand->writesize == 8192) //U0E
                {
                    size=8192;  
                    ret=nand_write(nand, off, &size, (u_char *)addr);

off+=8192;
                    addr+=2048;
                    ret=nand_write(nand, off, &size, (u_char *)addr);
                    off+=8192;
                    addr+=2048;
                    ret=nand_write(nand, off, &size, (u_char *)addr);
                    off+=8192;
                    addr+=2048;
                    ret=nand_write(nand, off, &size, (u_char *)addr);

off+=8192;
                    addr+=2048;
//写剩余的页面,这里的Uboot占用1M的NandFlash地址空间,在U0E里面占用128个页面(128Page=1M),上面已经写了四个页面了,这里写剩余的124个页,124个页面足够存放Uboot的有效数据了。
                    size=1024*1024-4*8192;
                    ret = nand_write(nand, off, &size, (u_char *)addr);
                }

现在我们重点要看 Uboot代码,uboot1.1.6/cpu/s3c64xx/nand_cp.c 文件:

 //该函数在Uboot.bin前8K代码中,这个函数实现把Uboot从Nandflash拷贝到外部内存中,是Uboot从Nandflash启动的关键地方

int copy_uboot_to_ram (void)

{
      int large_block = 0;
      int i;
      vu_char id;

        NAND_ENABLE_CE();
        NFCMD_REG=NAND_CMD_RESET;
        NF_TRANSRnB();

NFCMD_REG = NAND_CMD_READID;
        NFADDR_REG =  0x00;
        NF_TRANSRnB();
/* wait for a while */
        for (i=0; i<200; i++);

int factory = NFDATA8_REG;
        id = NFDATA8_REG;

int cellinfo=NFDATA8_REG;
        int tmp= NFDATA8_REG;

int childType=tmp & 0x03; //Page size

if (id > 0x80)
        {
            large_block = 1;
        }
        if(id == 0xd5 && childType==0x01 ) //K9GAG08U0D
        {
            large_block = 2;
        }else if(id == 0xd5 && childType==0x02 ) //
K9GAG08U0D
        {
            large_block = 3;
        }
    /* read NAND Block.
    * 128KB ->240KB because of U-Boot size increase. by scsuh
    * So, read 0x3c000 bytes not 0x20000(128KB).
    */
   return nandll_read_blocks(CFG_PHY_UBOOT_BASE, 0x3c000, large_block);

}

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==1)
        page_shift = 11;

if(large_block==2)
          page_shift = 12;

if(large_block==3)
                page_shift =13;

if(large_block == 2) // K9GAG08U0D

{
                /* Read pages */
         for (i = 0; i < 4; i++, buf+=(1<<(page_shift-1)))

{
                  nandll_read_page(buf, i, large_block);
          }

/* Read pages */
      for (i = 4; i < (0x3c000>>page_shift); i++, buf+=(1<<page_shift))

{
       nandll_read_page(buf, i, large_block);
     }
      }else if(large_block == 3)  //K9GAG08U0E
        {
            /* Read pages */
            for (i = 0; i < 4; i++, buf+=(1<<(page_shift-2))) 

            {
                    nandll_read_page(buf, i, large_block);
            }
            /* Read pages */
            for (i = 4; i < (0x3c000>>page_shift); i++, buf+=(1<<page_shift)) 

            {
                    nandll_read_page(buf, i, large_block);
            }
        }

    else
      {
            for (i = 0; i < (0x3c000>>page_shift); i++, buf+=(1<<page_shift))

{
                   nandll_read_page(buf, i, large_block);
               }
       }
        return 0;
}

static int nandll_read_page (uchar *buf, ulong addr, int large_block)
{
     int i;
     int page_size = 512;

     if (large_block==1)
         page_size = 2048;
     if (large_block==2)
         page_size = 4096;
     if(large_block==3)
         page_size = 8192;

       NAND_ENABLE_CE();
       NFCMD_REG = NAND_CMD_READ0;

        /* Write Address */ //5 个寻址周期,参看下图
        NFADDR_REG = 0;
        if (large_block)
       NFADDR_REG = 0;
       NFADDR_REG = (addr) & 0xff;
       NFADDR_REG = (addr >> 8) & 0xff;
       NFADDR_REG = (addr >> 16) & 0xff;


        if (large_block)
           NFCMD_REG = NAND_CMD_READSTART;

NF_TRANSRnB(); //等待NandFlash 状态引脚可读。

/* for compatibility(2460). u32 cannot be used. by scsuh */
       for(i=0; i < page_size; i++)

{
                *buf++ = NFDATA8_REG;
        }

NAND_DISABLE_CE();
        return 0;
}

寻址周期图:

具体的说明请参考K9GAG08U0E  DataSheet 第9页。

这里用两片文章写了s3c6410支持K9GAG08U0E 的关键地方,当然还有一些具体的细节了,比如给关键结构体 nand  chip, mtd_device 等赋值Page大小,Block大小,OOB大小的操作,硬件ECC 8bit 纠错等功能,当然这些不是K9GAG08U0E特有的功能,K9GAG08U0D也需要这样的操作,这里就不详细的介绍了。

希望这两篇文章对需要了解NandFlash如何通过软件工作的朋友有参考价值。

s3c6410 开发板Linux系统支持 K9GAG08U0E的方法(第二篇)相关推荐

  1. s3c6410 开发板Linux系统支持 K9GAG08U0E的方法

    由于NandFlash硬件升级比较快,公司去年一直在使用三星的K9GAG08U0D,现在MLC NandFlash 升级到了第二代,K9GAG08U0D 很快就会处在停产的状态,未雨绸缪,公司选型了K ...

  2. NUC980开发板Linux系统EC20模块 移植 串口 PPP拨号

    NUC980开发板Linux系统EC20模块 移植 串口 PPP拨号 1. EC20模块连接 2. Linux内核配置 3. 交叉编译PPP 4. 拨号脚本 5. 进行拨号 1. EC20模块连接 在 ...

  3. 基于全志A33开发板linux系统移植学习记录(Boot0)

    基于全志A33开发板linux系统移植学习记录 第一章 Boot0基于ARMGCC的编译与修改 文章目录 基于全志A33开发板linux系统移植学习记录 前言 一.全志A33简介以及上电引导流程 二. ...

  4. OK6410开发板linux系统下的SPI驱动和测试

    OK6410下的SPI驱动是可以用的,但是飞凌把它作为其它用途了,我们修改一些代码才能在/dev目录下创建SPI的设备节点文件 Step1:打开arch/arm/mach_s3c64XX/mach_m ...

  5. 迅为RK3399开发板Linux系统TFTP传输文件服务器测试

    本机测试:在/var/tftpboot 下面建立一个文件 test,在里面输入 hello world,然后保存该文件,如下图 再启动另一个终端,然后输入 tftp 127.0.0.1,如下图. 输入 ...

  6. linux imx6 书籍,迅为iMX6开发板-Linux系统-TFTP使用文档

    TFTP(Trivial File Transfer Protocol,简单文件传输协议),是一个基于 UDP 协议实 现的用于在客户机和服务器之间进行简单文件传输的协议,适合于开销不大.不复杂的应用 ...

  7. linux开发板 wifi配置,iTOP-4412开发板Linux系统下使用wifi模块配置

    精英版在 linux 下使用 wifi,需要进行下面的配置: 首先用户在拿到光盘资料以后查看下光盘里面的"linux"->"root_xxxxxxxx.tar.gz ...

  8. 编译linux系统到开发板,Linux系统有关交叉编译和移植到6410开发板上的简单过程...

    在进行移植之前,要检查一下目标机(这里指6410开发板)与宿主机之间的接线问题,即串口线.网线是否正确连接,目标机的电源是否插好!在接线问题解决后,才能保证交叉编译正常进行! 个人理解,移植的主要思想 ...

  9. Firefly-rk3288 开发板Linux系统编译

    前言 手上的一块Firefly-RK3288开发板,看了下Firefly提供的SDK,压缩包就有15个多G,直接吓退.还好最近看到了韦东山老师提供的教学资料.记下学习步骤及遇到的问题解决办法. 1.开 ...

  10. 使用xilinx最新工具vitis2019.2,定制zc702开发板linux系统

    目录 需要的工具 定制自己的zc702包 vivado定制znyq7020板级描述 petalinux定制linux发行版 zc702启动自定制的linux系统 小结和后续工作 需要的工具 2019年 ...

最新文章

  1. Java程序后台运行,即使关掉Putty终端
  2. 支付宝接口调用问题快速通道
  3. Python3并发检验代理池地址
  4. CMS:文章管理之视图(2)
  5. spring resttemplate 中文参数_SpringBoot使用RestTemplate访问第三方接口
  6. python正态检验_Python检验数据是否正态分布
  7. Safari 版本回退方法
  8. python语言输入两个数_python的函数输入两个参数吗
  9. 微信小程序 - 高级 - 深度实践 - wx:for 与 wx:for-items 与 wx:for-item 与 wx:key - 2 嵌套菜单的中文展示的方法 - 和官网不同
  10. 昔年浅谈成都的百度推广公司靠谱吗这个问题?!
  11. PPT,要你好看(全彩)pdf
  12. Android Studio实现学生信息管理系统,基础入门项目
  13. ssm框架的简要介绍
  14. Word高效指南 - 如何批量删除空格空白行
  15. 初学Spring Cloud踩得坑之Caused by: org.springframework.context.ApplicationContextException
  16. 机械键盘Windows键失效:Fn+Windows键解决
  17. 计算机网络结构化布线的六个子系统,结构化网络综合布线系统有六大子系统组成...
  18. VisualSVN提交叮叮机器人通知
  19. 四、搭建第一个直播系统
  20. Snowflake Snow Snowflakes

热门文章

  1. java怎么使用mfc,调用mfc方法
  2. 微信通讯录java实现的,小程序组件之仿微信通讯录的实现代码
  3. 大数据-浅谈hive优化
  4. 【1084】幂的尾数
  5. ubuntu翻译软件安装
  6. vue加d3js实现3d饼图
  7. 一文看懂抢注域名的相关问题解答
  8. JavaList集合根据ParentId递归【无限套娃】
  9. SQL语句查询:查询本周过生日的信息
  10. Python 导入包时报错 Traceback (most recent call last)