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 (include\configs)

  

2.4 修改链接脚本文件

  U-boot.lds (arch\arm\cpu) 链接脚本的修改,本版本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 (include\generated)
     * #define GENERATED_GBL_DATA_SIZE 192
     * JZ2440.h(include\config)
     * #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 启动,显示如下:

  

  

  

时间: 2024-10-08 11:02:43

u-boot移植(九)---代码修改---NAND的相关文章

u-boot移植(十二)---代码修改---支持DM9000网卡

一.准备工作 1.1 原理图 CONFIG_DM9000_BASE 片选信号是接在nGCS4引脚,若要确定网卡的基地址,则要根据片选信号的接口去确定. 在三星2440的DATASHEET中memory control这一章的Figure 5-1. S3C2440A Memory Map after Reset 已经说明了片选4的地址,如下: 只要发出的信号在 0x20000000--0x28000000 之间,就会使得片选4引脚变为低电平.所以可以确定我们网卡的基地址为0x20000000. C

js代码从页面移植到文件中失效或js代码修改后不起作用的解决办法

最近在做关于网站的项目,总是发生这样的问题 写的javascript代码在页面上没有问题,但是将js代码移植到.js的文件中,在页面上进行调用,总是出现失效等错误 另外修改后的js代码,重新刷新网页仍然不起作用 经过大量搜索并经过验证,可以用下面方法来解决 将js代码封装到js文件中失效的原因可能是js文件中存在中文注释,导致在执行的时候中断,在js文件尽量不要写中文注释 修改后的js代码刷新网页后不起效果可能是因为你所用的浏览器使用缓存的问题,可在浏览器中设置取消使用缓存,并删除临时文件,重启

在使用shape的同时,用代码修改shape的颜色属性

Android里面经常会使用shape来定制一些View的背景 可以修改View的背景颜色,形状等属性 一般情况下,shape都是在xml文件里面写死了,今天遇到一个需求,View的形状是圆角的,但是颜色是在代码里面设置的 最开始的思路是先在代码里给View设置颜色,再在shape里面设置solid属性为透明色 <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="htt

一次js代码修改不更新问题的解决

今天遇到一个问题,虽说问题不大,但弄得本人脑袋发麻 我讲javascript修改后,刷新页面或者清除浏览器缓存,修改后的效果也不出现,害的我好苦啊 最后想到自己是新装的机子是不是是浏览器设置的原因 按以下方式完美解决 这应该是开发人员必须设置的 一次js代码修改不更新问题的解决,布布扣,bubuko.com

钩取API之代码修改方法【一】

IAT方式就不去花精力了,加了壳的程序用这方法压根用不上. 就熟悉一下代码修改方法.书上用的是隐藏进程的实例 第一种办法 一,枚举进程,给所有进程加载DLL[用远程线程注入] 二,传入需要隐藏的进程名 三,判断有没有修改过需要钩取的函数,如果还没有修改过就改掉,跳向自己的函数,同时保存好原来的值 四,在自己的替代函数里将原来的值修改回去,并再执行一次,执行完做相关处理 五,在自己的替代函数最后再钩取函数,修改跳转到替代函数 基本逻辑就是这样,像是移花接木啊... DLL代码: #define S

am335x UART1输入u-boot 调试信息代码修改

AM335x 调试信息UART1输出代码修改1. 关于pin_mux  的配置代码修改位置:/board/forlinx/ok335x/mux.c 1 void enable_uart0_pin_mux(void) 2 { 3 configure_module_pin_mux(uart0_pin_mux_spl); 4 configure_module_pin_mux(uart1_pin_mux); 5 } 6 将这行代码打开. 代码跟踪流程:arch/arm/cpu/armv7/start.S

iOS代码修改音量

最近在做一个项目,需要用户在打开APP后,自动将音量调节到某个值,于是研究了一下. 之前做过iOS上声音的研究,苹果对iPhone设备的输入/输出的控制很严格,因为苹果要控制用户体验的一致性.比如:用户将耳机拔下来的时候,苹果认为,用户这时候不希望其他人知道自己在听什么,于是这时候声音会被自动暂停.在音量调整上,苹果也采取了类似的策略.苹果认为,用户不需要APP来为他指定音量,因为这样有时候用户会感到不舒服.苹果的开发文档是这么说的: You cannot change device volum

做web项目时对代码修改后浏览器端不生效的应对方法(持续更新)

做web项目时,经常会遇到修改了代码,但浏览器端没有生效,原因是多种多样的,我会根据我遇到的情况逐步更新解决办法 1.运行的时候采用debug模式,一般情况下使用项目部署按钮右边那个按钮下的tomcat7中的run就行,如果使用的是serves中的run serves,这种情况貌似不会自动编译 2.点击project菜单下的clean选项,在打开的窗口中选择你使用的项目,ok,这样会删除tomcat容器中关于该项目的一些信息,然后重新部署,运行 3.删除电脑中tomcat文件夹,重新解压,然后在

WPF DataGrid分页功能实现代码 修改原作者不能实现的部分

这两天需要给Datagrid加个分页,查找了一些相关的文章,发现有一个写了一个控件比较好,地址是 http://blog.csdn.net/zdw_wym/article/details/8221894 感谢这位大神12年的帖子,但是照着做了以后,发现除了点击数字和GO按钮好使意外,神马“首页.上一页.下一页.末页”都不好使. 继续找寻相关的资料和查看大神的源码,发现有的地方写的不对,因为textblock没有click事件,而大神写了click事件,所以没有得到触发,介于这个问题,我稍作了修改