zoukankan      html  css  js  c++  java
  • u-boot移植(九)---代码修改---NAND

    一、NAND原理

      

      NAND 无地址空间,地址和数据的发送都依赖于LDATA[0:7]这一串数据总线。

      

       不看随机页编程,看到从高位到低位的页,总共分为64个页面,每个页的组成是2K + 64  个byte,一个块的大小是(128K + 4K)byte,64页组成一块。

    1.1 NAND Flash的编址

      nand flash的的页的大小是(2048 + 64)byte,64这个数据是不参与编址的。

      访问 nand flash:

      • 发出命令:读、写、擦除
      • 发出地址
      • 传输数据

       命令设置如下:

      

    1.2 nand flash的访问

      

      可以看看上面的模式选择,然后对应引脚进行操作,就可以进行读写操作。命令和数据就通过这些引脚来进行操作。但是不必直接操作这些引脚,可以通过寄存器来进行操作。

      查看S3C2440的手册,可以看到如下的信息:

      

      写命令寄存器就相当于NAND Flash寄存器命令周期,写地址寄存器就相当于NAND Flash寄存器的地址周期......

       我们的NAND Flash是X8的,即是8位NAND Flash,对应2440上面的一些控制寄存器:

      NAND Flash命令寄存器:

      

      地址寄存器:

      

      数据寄存器:

      

      状态寄存器:

      

      还有一些其他寄存器是与读写有关的。

      操作这些寄存器,2440会自动驱动PIN脚给出信号。

    二、u-boot中设置nand启动

    2.1 建立init.c

      这是NAND启动的初始化文件,里面包含了nand启动的初始化函数。代码添加到 borad/samdung/jz2440/ 目录下:

      1 /* NAND FLASH控制器 */
      2 #define NFCONF (*((volatile unsigned long *)0x4E000000))
      3 #define NFCONT (*((volatile unsigned long *)0x4E000004))
      4 #define NFCMMD (*((volatile unsigned char *)0x4E000008))
      5 #define NFADDR (*((volatile unsigned char *)0x4E00000C))
      6 #define NFDATA (*((volatile unsigned char *)0x4E000010))
      7 #define NFSTAT (*((volatile unsigned char *)0x4E000020))
      8 
      9 /* GPIO */
     10 #define GPHCON              (*(volatile unsigned long *)0x56000070)
     11 #define GPHUP               (*(volatile unsigned long *)0x56000078)
     12 
     13 /* UART registers*/
     14 #define ULCON0              (*(volatile unsigned long *)0x50000000)
     15 #define UCON0               (*(volatile unsigned long *)0x50000004)
     16 #define UFCON0              (*(volatile unsigned long *)0x50000008)
     17 #define UMCON0              (*(volatile unsigned long *)0x5000000c)
     18 #define UTRSTAT0            (*(volatile unsigned long *)0x50000010)
     19 #define UTXH0               (*(volatile unsigned char *)0x50000020)
     20 #define URXH0               (*(volatile unsigned char *)0x50000024)
     21 #define UBRDIV0             (*(volatile unsigned long *)0x50000028)
     22 
     23 #define TXD0READY   (1<<2)
     24 
     25 
     26 void nand_read_ll(unsigned int addr, unsigned char *buf, unsigned int len);
     27 
     28 /* 判定是否是nor启动 */
     29 static int isBootFromNorFlash(void)
     30 {
     31     volatile int *p = (volatile int *)0;
     32     int val;
     33 
     34     val = *p;
     35     *p = 0x12345678;
     36     if (*p == 0x12345678)
     37     {
     38         /* 写成功, 是nand启动 */
     39         *p = val;
     40         return 0;
     41     }
     42     else
     43     {
     44         /* NOR不能像内存一样写 */
     45         return 1;
     46     }
     47 }
     48 
     49 /* 拷贝代码到sdram */
     50 void copy_code_to_sdram(unsigned char *src, unsigned char *dest, unsigned int len)
     51 {    
     52     int i = 0;
     53     
     54     /* 如果是NOR启动 */
     55     if (isBootFromNorFlash())
     56     {
     57         while (i < len)
     58         {
     59             dest[i] = src[i];
     60             i++;
     61         }
     62     }
     63     else
     64     {
     65         //nand_init();
     66         nand_read_ll((unsigned int)src, dest, len);
     67     }
     68 }
     69 
     70 /* 清除BSS */
     71 void clear_bss(void)
     72 {
     73     extern int __bss_start, __bss_end;
     74     int *p = &__bss_start;
     75     
     76     for (; p < &__bss_end; p++)
     77         *p = 0;
     78 }
     79 
     80 /* nand初始化 */
     81 void nand_init_ll(void)
     82 {
     83 #define TACLS   0
     84 #define TWRPH0  1
     85 #define TWRPH1  0
     86     /* 设置时序 */
     87     NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);
     88     /* 使能NAND Flash控制器, 初始化ECC, 禁止片选 */
     89     NFCONT = (1<<4)|(1<<1)|(1<<0);    
     90 }
     91 
     92 static void nand_select(void)
     93 {
     94     NFCONT &= ~(1<<1);    
     95 }
     96 
     97 static void nand_deselect(void)
     98 {
     99     NFCONT |= (1<<1);    
    100 }
    101 
    102 static void nand_cmd(unsigned char cmd)
    103 {
    104     volatile int i;
    105     NFCMMD = cmd;
    106     for (i = 0; i < 10; i++);
    107 }
    108 
    109 static void nand_addr(unsigned int addr)
    110 {
    111     unsigned int col  = addr % 2048;
    112     unsigned int page = addr / 2048;
    113     volatile int i;
    114 
    115     NFADDR = col & 0xff;
    116     for (i = 0; i < 10; i++);
    117     NFADDR = (col >> 8) & 0xff;
    118     for (i = 0; i < 10; i++);
    119     
    120     NFADDR  = page & 0xff;
    121     for (i = 0; i < 10; i++);
    122     NFADDR  = (page >> 8) & 0xff;
    123     for (i = 0; i < 10; i++);
    124     NFADDR  = (page >> 16) & 0xff;
    125     for (i = 0; i < 10; i++);    
    126 }
    127 
    128 static void nand_wait_ready(void)
    129 {
    130     while (!(NFSTAT & 1));
    131 }
    132 
    133 static unsigned char nand_data(void)
    134 {
    135     return NFDATA;
    136 }
    137 
    138 void nand_read_ll(unsigned int addr, unsigned char *buf, unsigned int len)
    139 {
    140     int col = addr % 2048;
    141     int i = 0;
    142         
    143     /* 1. 选中 */
    144     nand_select();
    145 
    146     while (i < len)
    147     {
    148         /* 2. 发出读命令00h */
    149         nand_cmd(0x00);
    150 
    151         /* 3. 发出地址(分5步发出) */
    152         nand_addr(addr);
    153 
    154         /* 4. 发出读命令30h */
    155         nand_cmd(0x30);
    156 
    157         /* 5. 判断状态 */
    158         nand_wait_ready();
    159 
    160         /* 6. 读数据 */
    161         for (; (col < 2048) && (i < len); col++)
    162         {
    163             buf[i] = nand_data();
    164             i++;
    165             addr++;
    166         }
    167         
    168         col = 0;
    169     }
    170 
    171     /* 7. 取消选中 */        
    172     nand_deselect();
    173 }

      修改 borad/samdung/jz2440/ 目录下的 makefile:

      

    2.2 去掉代码重定位

      去掉 -pie 选项:

      

      注释掉第82行:

      

    2.3 修改代码链接地址

      Jz2440.h (includeconfigs) 

      

    2.4 修改链接脚本文件

      U-boot.lds (archarmcpu) 链接脚本的修改,本版本u-boot将一个文件夹下面的c文件都链接成一个.o文件,名字为built-in.o,所以我们直接写上built-in.o即可。

      

      

      将这两个built-in.o放入链接脚本当中:

      

    2.5 修改 board_init_f

      在crt0.S中设置nand 启动的代码:

      

      这一段代码就是 nand 重定位代码了。CONFIG_SYS_TEXT_BASE 是自己设置的,可以自行设置大小。

      接下来的代码就是跳转到 board_init_f_mem 和 board_init_f 中执行初始化。

       init_sequence_f 链表中要注释掉下面两行,并更改:

      

    2.6 修改重定位代码

      首先在board_init_f(Board_f.c (common) )添加返回函数:

      

     1 unsigned int board_init_f(ulong boot_flags)
     2 {
     3 
     4     gd->flags = boot_flags;
     5     gd->have_console = 0;
     6 
     7     if (initcall_run_list(init_sequence_f))
     8         hang();
     9 #if 0
    10 #if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX) && 
    11         !defined(CONFIG_EFI_APP)
    12     /* NOTREACHED - jump_to_copy() does not return */
    13     hang();
    14 #endif
    15 #endif
    16     return (unsigned int)(gd->new_gd);  //添加的返回值,返回id供 board_init_r调用
    17 }

      board_init_f 函数原型记得在 include/common中也修改。

      修改crt0.S 代码如下:

    ENTRY(_main)
    
    /*
     * Set up initial C runtime environment and call board_init_f(0).
     * 初始化C运行环境并且调用 board_init_f(0) 函数
     */
    
     /*
      * 初始化栈地址
      */
    #if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
        ldr    sp, =(CONFIG_SPL_STACK)
    #else
        /* Generic-asm-offsets.h (includegenerated)
         * #define GENERATED_GBL_DATA_SIZE 192
         * JZ2440.h(includeconfig)
         * #define PHYS_SDRAM_1        0x30000000
         * #define CONFIG_SYS_SDRAM_BASE    PHYS_SDRAM_1
         * #define CONFIG_SYS_INIT_SP_ADDR    (CONFIG_SYS_SDRAM_BASE + 0x1000 - GENERATED_GBL_DATA_SIZE)
         * 
         * CONFIG_SYS_INIT_SP_ADDR = 0x30000000 + 0x1000 - 192(0xc0) = 0x30000f40
         */
        ldr    sp, =(CONFIG_SYS_INIT_SP_ADDR)        /* 设置CFIG_SYS_INIT_SP_ADDR定义的地址,include/configs/jz2440.h中定义 */
    #endif
    #if defined(CONFIG_CPU_V7M)    /* v7M forbids using SP as BIC destination */
        mov    r3, sp
        bic    r3, r3, #7
        mov    sp, r3
    #else
        /* sp 的8字节对齐 */
        bic    sp, sp, #7    /* 8-byte alignment for ABI compliance */
    #endif
        /* 设置nand 启动 */
        bl nand_init_ll    /* 跳转到borad/samsung/jz2440/init.c 中执行 nand_init_ll 函数 */
        
        mov r0, #0
        ldr r1, =(CONFIG_SYS_TEXT_BASE)    /*CONFIG_SYS_TEXT_BASE=0x33f00000 程序的链接地址*/
        ldr r2, =0x100000                /* 程序大小 */    
        bl copy_code_to_sdram            /* 拷贝代码到SDRAM */
        
        bl clear_bss                    /* 清除bss */
    
        ldr pc, =call_board_init_f            /* 执行第一阶段初始化 */
    
        bl call_board_init_r            /* 执行第二阶段代码 */
    
        adr lr, here                 /*设置返回地址为下面的here,重定位到sdram后返回here运行*/
        ldr r0, [r9, #GD_RELOC_OFF]     /* r0 = gd->reloc_off 取重定位地址偏移值 */
        add lr, lr, r0                /*返回地址加偏移地址等于重定位后在sdram中的here地址*/
    
    here:        /*返回后跳到sdram中运行    */    
        /*
          * now relocate vectors
          */
        bl    relocate_vectors
    
        /* Set up final (full) environment */
        bl    c_runtime_cpu_setup    /* we still call old routine here */
    
        
    call_board_init_f:
        mov    r0, sp                    /* r0 = sp */
        bl    board_init_f_mem        /*跳转到 board_init_f_mem 执行*/
        mov    sp, r0                    
    
        mov    r0, #0
        bl    board_init_f            /* 调用单板的初始化函数,跳转到 borad_init_f 处执行 */
    
    call_board_init_r:
        ldr    r1, =CONFIG_SYS_TEXT_BASE
        /* call board_init_r */
        bl board_init_r    /* this is auto-relocated! */
    ENDPROC(_main)

      here的代码一定不能注释掉,注释掉后就启动不了

    2.7 去掉-pie选项

      如下图:

      

      

     三、编译烧写

      make CROSS_COMPILE=arm-2440-linux-gnueabi-

      

      生成的 u-boot.bin 有470K 左右。

      然后通过jtag 工具直接烧写进nand 的  0地址中,拨码开关拨到 nand 启动,显示如下:

      

      

      

  • 相关阅读:
    火狐推荐几个实用的插件
    Ubuntu下安装可视化SVN客户端Rabbitvcs
    thunderbird中如何设置QQ邮箱
    Ubuntu 10.04里安装强大抓图工具Shutter
    cannot start compilation;the output path is not specified for module specify the output path in the project structure dialog
    jrebel+idea 进行热部署配置
    jeecg数据库切换至mysql8.0方式
    com.alibaba.druid.pool.DruidDataSource 使用druid数据源 No supported DataSource type found
    租户的基本信息表
    kettle系列-我的开源kettle调度、管理平台[kettle-manager]介绍
  • 原文地址:https://www.cnblogs.com/kele-dad/p/7019827.html
Copyright © 2011-2022 走看看