一、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/ 目录下:

 /* NAND FLASH控制器 */
#define NFCONF (*((volatile unsigned long *)0x4E000000))
#define NFCONT (*((volatile unsigned long *)0x4E000004))
#define NFCMMD (*((volatile unsigned char *)0x4E000008))
#define NFADDR (*((volatile unsigned char *)0x4E00000C))
#define NFDATA (*((volatile unsigned char *)0x4E000010))
#define NFSTAT (*((volatile unsigned char *)0x4E000020)) /* GPIO */
#define GPHCON (*(volatile unsigned long *)0x56000070)
#define GPHUP (*(volatile unsigned long *)0x56000078) /* UART registers*/
#define ULCON0 (*(volatile unsigned long *)0x50000000)
#define UCON0 (*(volatile unsigned long *)0x50000004)
#define UFCON0 (*(volatile unsigned long *)0x50000008)
#define UMCON0 (*(volatile unsigned long *)0x5000000c)
#define UTRSTAT0 (*(volatile unsigned long *)0x50000010)
#define UTXH0 (*(volatile unsigned char *)0x50000020)
#define URXH0 (*(volatile unsigned char *)0x50000024)
#define UBRDIV0 (*(volatile unsigned long *)0x50000028) #define TXD0READY (1<<2) void nand_read_ll(unsigned int addr, unsigned char *buf, unsigned int len); /* 判定是否是nor启动 */
static int isBootFromNorFlash(void)
{
volatile int *p = (volatile int *);
int val; val = *p;
*p = 0x12345678;
if (*p == 0x12345678)
{
/* 写成功, 是nand启动 */
*p = val;
return ;
}
else
{
/* NOR不能像内存一样写 */
return ;
}
} /* 拷贝代码到sdram */
void copy_code_to_sdram(unsigned char *src, unsigned char *dest, unsigned int len)
{
int i = ; /* 如果是NOR启动 */
if (isBootFromNorFlash())
{
while (i < len)
{
dest[i] = src[i];
i++;
}
}
else
{
//nand_init();
nand_read_ll((unsigned int)src, dest, len);
}
} /* 清除BSS */
void clear_bss(void)
{
extern int __bss_start, __bss_end;
int *p = &__bss_start; for (; p < &__bss_end; p++)
*p = ;
} /* nand初始化 */
void nand_init_ll(void)
{
#define TACLS 0
#define TWRPH0 1
#define TWRPH1 0
/* 设置时序 */
NFCONF = (TACLS<<)|(TWRPH0<<)|(TWRPH1<<);
/* 使能NAND Flash控制器, 初始化ECC, 禁止片选 */
NFCONT = (<<)|(<<)|(<<);
} static void nand_select(void)
{
NFCONT &= ~(<<);
} static void nand_deselect(void)
{
NFCONT |= (<<);
} static void nand_cmd(unsigned char cmd)
{
volatile int i;
NFCMMD = cmd;
for (i = ; i < ; i++);
} static void nand_addr(unsigned int addr)
{
unsigned int col = addr % ;
unsigned int page = addr / ;
volatile int i; NFADDR = col & 0xff;
for (i = ; i < ; i++);
NFADDR = (col >> ) & 0xff;
for (i = ; i < ; i++); NFADDR = page & 0xff;
for (i = ; i < ; i++);
NFADDR = (page >> ) & 0xff;
for (i = ; i < ; i++);
NFADDR = (page >> ) & 0xff;
for (i = ; i < ; i++);
} static void nand_wait_ready(void)
{
while (!(NFSTAT & ));
} static unsigned char nand_data(void)
{
return NFDATA;
} void nand_read_ll(unsigned int addr, unsigned char *buf, unsigned int len)
{
int col = addr % ;
int i = ; /* 1. 选中 */
nand_select(); while (i < len)
{
/* 2. 发出读命令00h */
nand_cmd(0x00); /* 3. 发出地址(分5步发出) */
nand_addr(addr); /* 4. 发出读命令30h */
nand_cmd(0x30); /* 5. 判断状态 */
nand_wait_ready(); /* 6. 读数据 */
for (; (col < ) && (i < len); col++)
{
buf[i] = nand_data();
i++;
addr++;
} col = ;
} /* 7. 取消选中 */
nand_deselect();
}

  修改 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) )添加返回函数:

  

 unsigned int board_init_f(ulong boot_flags)
{ gd->flags = boot_flags;
gd->have_console = ; if (initcall_run_list(init_sequence_f))
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
return (unsigned int)(gd->new_gd);  //添加的返回值,返回id供 board_init_r调用
}

  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, #
mov sp, r3
#else
/* sp 的8字节对齐 */
bic sp, sp, # /* 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 启动,显示如下:

  

  

  

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

  1. -boot移植(十一)---代码修改---支持nandflash

    一.移植前的修改 1.1 include/configs/jz2440修改 原来的定义: 可以看出,要先定义CONFIG_CMD_NAND才能使能NANDFlash. 这个在我们文件中的82行有定义, ...

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

    一.准备工作 1.1 原理图 CONFIG_DM9000_BASE 片选信号是接在nGCS4引脚,若要确定网卡的基地址,则要根据片选信号的接口去确定. 在三星2440的DATASHEET中memory ...

  3. ok6410 u-boot-2012.04.01移植六完善MLC NAND支持

    继ok6410 u-boot-2012.04.01移植四.五后,开发板基本已支持MLC NAND,支持DM9000.但是通过NAND命令更新u-boot到NAND,还存在问题,需要根据u-boot的n ...

  4. spring boot / cloud (九) 使用rabbitmq消息中间件

    spring boot / cloud (九) 使用rabbitmq消息中间件 前言 rabbitmq介绍: RabbitMQ是一个在AMQP基础上完整的,可复用的企业消息系统.它可以用于大型软件系统 ...

  5. spring Boot(十九):使用Spring Boot Actuator监控应用

    spring Boot(十九):使用Spring Boot Actuator监控应用 微服务的特点决定了功能模块的部署是分布式的,大部分功能模块都是运行在不同的机器上,彼此通过服务调用进行交互,前后台 ...

  6. Android之vector代码修改颜色

    前言:google给了很多material design icon,在开发过程中,可以下载下来直接使用,下载地址为https://materialdesignicons.com/ . 1.下载图标,并 ...

  7. Asp.net使用代码修改配置文件的节点值

    使用代码修改配置文件的方法: 1.打开配置文件写入的权限 2.先按节点名称长到要修改的节点,然后删除,紧接着将有新值的节点添加回去 3.关闭配置文件写入的权限 修改Appsetting节点的值,修改其 ...

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

    AM335x 调试信息UART1输出代码修改1. 关于pin_mux  的配置代码修改位置:/board/forlinx/ok335x/mux.c void enable_uart0_pin_mux( ...

  9. SharePoint开发 - 使用Session(代码修改webconfig)

    博客地址 http://blog.csdn.net/foxdave SharePoint启用Session可以使用Powershell,戳这里:可以修改webconfig. 本篇叙述的重点是通过fea ...

随机推荐

  1. python 深入浅出装饰器(decorator)--举的例子关于星级争霸2(starcraft2)

    其实早就想写一篇深入浅出装饰器的文章,苦于一直没有找到很好的例子描述,自己除了在写api参数检测和日志打印的时候用到以外,其他地方也没有什么重度使用所以一直没有写. 我不会讲解装饰器的理论,还有各种基 ...

  2. 关于pycharm的debugger配置问题(包含启用py.test测试)

    今天才发现了一个刷新三观的问题.那就是 pycharm的底层集成的debugger功能其实是依赖于几个测试框架.. 现在由于要写基于pytest的测试,但是如果到zsh里面去跑命令,明显是效率很低下的 ...

  3. 下载系统已经安装的rpm包

    下载系统已经安装的rpm包 yum -y install yum-utils 安装yum下载工具 yumdownloader mysql 用yum下载到当前目录 实例:查询mysql安装包[root@ ...

  4. mybatis 一对多的注入 指的是连表查询时候 将不同的查询结果以列表存储对象形式 注入进去 多对一指的是 查询多条结果但都是一样的 只需注入一条

    mybatis 一对多的注入 指的是连表查询时候 将不同的查询结果以列表存储对象形式 注入进去 多对一指的是 查询多条结果但都是一样的 只需注入一条

  5. ceph 安装ceph问题汇总

    1.在不同节点安装ceph时,出现以下异常: 参考这里 ceph deploy RuntimeError: NoSectionError: No section: 'ceph' 解决方法: 在报错的机 ...

  6. BZOJ4001 TJOI2015概率论(生成函数+卡特兰数)

    设f(n)为n个节点的二叉树个数,g(n)为n个节点的二叉树的叶子数量之和.则答案为g(n)/f(n). 显然f(n)为卡特兰数.有递推式f(n)=Σf(i)f(n-i-1) (i=0~n-1). 类 ...

  7. MT【12】三点坐标求面积

    $L_1,L_2$是O发出的两条射线,C是一个常数,一条动直线$l$分别与$L_1,L_2$交于A,B两点.$S_{\Delta ABC}=C$,求A,B的中点D的轨迹方程.(2012北大自主招生) ...

  8. pdo连接的时候设置字符编码是这样的

    $pdo = new \PDO(..,..,..) $pdo->query('SET NAMES utf8mb4'); $pdo->exex('sql....');

  9. 恕我直言,在座的各位根本写不好Java!

    其实,本不想把标题写的那么恐怖,只是发现很多人干了几年 Java 以后,都自认为是一个不错的 Java 程序员了,可以拿着上万的工资都处宣扬自己了,写这篇文章的目的并不是嘲讽和我一样做 Java 的同 ...

  10. Spring Cloud(四) --- config

    Spring Cloud Config 随着线上项目变的日益庞大,每个项目都散落着各种配置文件,如果采用分布式的开发模式,需要的配置文件随着服务增加而不断增多.某一个基础服务信息变更,都会引起一系列的 ...