UBOOT如何从norflash和nandflash启动

转自:http://www.aiuxian.com/article/p-2796357.html

 

电子产品如果没有了电,就跟废品没什么区别,是电赋予了他们生命,然而程序则是他们的灵魂。

小时候一直很好奇,一个个死板的电子产品为什么一上电以后就能够工作了呢?为什么一个小小芯片就能够运行我们编写的程序呢?一个开发板从刚上电到整个操作系统能够运行起来是怎么办到的呢?这些东西困扰了好久,参考了好多资料现在才慢慢弄明白其中一些原理。

我们现在接触的大多数电子产品都是使用数字电路设计出来的,数字电路的精髓就是两个数字:0和1,这两个数字千变万化的组合创造了计算机世界的缤纷多彩,不管是cpu、内存还是其他外设都是通过0和1的变化来进行记录、交互以及计算。硬件是怎么操作这两个数字以及这两个数字是怎么控制硬件工作的,这里不进行讨论,那都是一些二极管、三极管、与非门、信号放大取样编码等等知识,所以这里将对一个个功能完整的芯片,从上电以后,他们通过电信号完成各种操作的过程进行解析。如果有玩过单片机的同学应该知道,一个cpu加上一个电源,然后外接一个外部晶振就能够做成一个最小系统了,单片机就能够在他可怜的64k或者128k内存中运行起来了,这些简单的控制芯片虽然有它的存在价值,但是它不能满足日益复杂的计算需求,所以需要更快的运算速度以及更大的运行内存,因此我们会用到更复杂的处理器,比如mips、arm等。下面将使用arm s3c2440 处理器分析上电启动的过程。

作为一个嵌入式产品,它的多样性让它更具有可玩性,以及更容易适应不同的需求,它不像我们的PC启动方式相对比较单一(ROM启动),arm启动方式有从norfalsh启动、nandflash启动、SD卡启动和UBS启动等,但是他们的启动原理都是大同小异的。

开始之前,先理清几个概念

SDRAM(Synchronous Dynamic Random Access Memory):同步动态随机存取存储器,同步是指Memory工作需要步时钟,内部的命令的发送与数据的传输都以它为基准;动态是指存储阵列需要不断的刷新来保证数据不丢失;随机是指数据不是线性依次存储,而是由指定地址进行数据读写,简单的说,它就是cpu使用的外部内存,即我们常说的内存条

SRAM是英文Static RAM的缩写,它是一种具有静止存取功能的内存,不需要刷新电路即能保存它内部存储的数据,速度比SDRAM快,一般用作高速缓冲存储器(Cache)

norflash:非易失闪存,是一种外部存储介质,芯片内执行(XIP,eXecute In Place),这样应用程序可以直接在flash闪存内运行,不必再把代码读到系统RAM中,由于它有地址总线,cpu可以直接从norflash中取指,直接从FLASH中运行程序,但是工艺复杂,价格比较贵,容量较小(1~4M),NOR的传输效率很高

nandflash:它也是非易失闪存(掉电不丢失)的一种,但是它虽然有数据总线,但是没有地址总线,所以cpu不能直接从nandflash中取指运行,由于它价格便宜,所以常常用来存储大量数据,和我们常说的硬盘类似。

下面将解析nandflash启动和norflash启动两种方式(arm s3c2440),其他启动方式将在uboot代码部分分析。

一、 Nandflash启动

 

 

 

 

首先必须把一个正确的bootload烧写到nandflash的最低位置,即从0x000开始烧写。当我们选择从nandflash启动开发板的时候,开发板就会启动连接nandflash的电路结构,当开发板一上电的时候,Nand Flash控制器会自动的把Nand Flash上的前4K数据搬移到CPU的内部RAM中(SRAM-cache),这个内部RAM我们通常称作stepping stone,同时把这段片内SRAM映射到nGCS0片选的空间(即0x00000000),CPU从内部RAM的0x00000000位置开始启动(执行),这个过程不需要程序干涉的

这个过程就是启动过程的stage1,它将nandflash的前4看内容拷贝到stepping stone中,然后从stepping stone的第一条指令开始执行,这4k内容里面的指令将会完成以下几个动作

1.硬件设备初始化

2. 加载U-Boot第二阶段代码到SDRAM空间

3. 设置好栈

4. 跳转到第二阶段stage2代码入口

 

从下图我们可以看到,板子重置以后,内存的映射关系。从图中可以看到以下几点:

1.刚开始bank0~bank5是只能映射SROM的,而bank6和bank7才能够接SDRM,而且每个bank最大接128M的SDRM,所以决定了S3C2440的最大可外接SDRAM是256M;

2.从图中我们可以看到bank6的起始地址是0x3000_0000, 所以我们在执行stage1的第二个动作(加载U-Boot第二阶段代码到SDRAM空间)时,需要将uboot代码放到0x3000_000~0x4000_0000区间内(SDRAM内),才能从SDRAM中正常执行stage2;

3.当没有选择从nandflash启动时,Boot internal SRAM(4k)的起始地址是0x4000_0000, 当选择从nandflash启动时,Boot internal SRAM(4k)的起始地址是0x00, 因为我们的开发板没有外接SROM,所以bank1~bank5都是空闲的,而bank0的位置将被Boot internal SRAM(4k)替代,也就是说bank0的前4k就是stepping stone(起步石),板子上电以后,在nandflash的启动模式下,S3C2440在硬件上会完成下图中的地址映射,并自动将nandflash中的前4k拷贝到stepping stone中,并从stepping stone的开始地址(0x00)获取到第一条指令并执行。

 

 

 

 

经过上面的分析后,我们可以将上面两图合并成下图所示:

 

 

 

前面说了nandflash启动过程中第一个代码搬移,下面将解析第二个代码搬移,这4k代码首先会设置cpu运行模式,关看门狗,设置时钟,关中断,初始化内存,初始化nandflash,设置堆栈,然后将整个bootload搬运到SDRAM中,并跳转到SDRAM中执行。

基本过程如下图所示:

          

 

 

关于4k代码的执行过程将会在后面详细解释,而且在新的uboot-2015中,这4k代码是由uboot_spl.bin完成的,下面将基于uboot-2015.10 列出uboot从上电到启动内核的整个过程进行概述

 

 

 

 

 

二、norflash启动

其实理解了nandflash的启动方式,norflash的启动也就好理解多了,首先需要知道的是norflash是可以在片上执行代码(XIP)的,也就是说,我们只需要将bootload烧写到norflash的开始地址,当开发板上电以后,从内存映射图可以知道,nor flash会被映射到0x00000000地址(就是nGCS0,这里就不需要片内SRAM来辅助了,所以片内SRAM的起始地址还是0x40000000,不会改变),然后cpu从0x00000000开始执行(也就是在Norfalsh中执行)整个uboot,直到引导内核启动。

从norflash启动可以省事多了,不仅如此,我们自己编写的裸机程序需要调试,一般也是直接烧写到norflash中进行的,因为只要我们将编译好的可执行文件放到norflash的开始,开发板上电以后就会从norflash的第一条指令开始取指执行,我们后面写裸机程序的调试就是用这种方式进行的。

从norflash启动虽然从开发的角度会很方便(其实也方便不了多少),但是从产品的角度却增加了它的成本,毕竟norflash还是相对较贵的,我们明明只要一块nandflash就足够启动整个开发板了,就没必要在产品中添加一块norflash了,只要代码改改就能省下不少成本,何乐不为。而且nandflash对产品是必不可少的,因为后面还要存放内核和文件系统,起码需要几十兆的空间,用norflash来存储也不现实。

也许你会想,能不能只用norflash,不用nandflash和SDRAM行不行呢,毕竟norflash即可以存储,也可以运行程序的啊,从理论来说是可以的,但是了解一下他们的市场价格、运行速度和工作原理,应该就会知道答案了。

 

总结

这里只例举了两种启动方式,还有其他的启动方式将在uboot代码中分析,这篇文章只是一个引子和一个概述,后面将具体分析一个开发板是怎么从一个废品通上电以后体现了它的价值,请看后面的文章,了解bootload中的前4k代码到底干了什么!

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是在 U-Boot 中读写 NOR Flash 的示例代码: 1. NOR Flash 初始化 ```c #include <common.h> #include <command.h> #include <asm/io.h> #include <asm/nor.h> int do_nor_init(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { nor_info_t nor; /* 初始化 NOR Flash */ nor_init(&nor); /* 设置 NOR Flash 为 16-bit 模式 */ nor_set_16bit(&nor); /* 打印 NOR Flash 的信息 */ print_nor_flash_info(&nor); return 0; } U_BOOT_CMD(nor_init, 1, 1, do_nor_init, "Initialize NOR Flash", ""); ``` 2. NOR Flash 读取 ```c #include <common.h> #include <command.h> #include <asm/io.h> #include <asm/nor.h> int do_nor_read(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { nor_info_t nor; ulong addr; int len; uchar *buf; /* 解析参数 */ if (argc != 4) return CMD_RET_USAGE; addr = simple_strtoul(argv[1], NULL, 16); len = simple_strtoul(argv[2], NULL, 10); buf = (uchar *)simple_strtoul(argv[3], NULL, 16); /* 初始化 NOR Flash */ nor_init(&nor); /* 读取 NOR Flash */ nor_read(&nor, addr, len, buf); /* 打印读取的数据 */ print_buffer(addr, buf, 16, len / 16 + 1); return 0; } U_BOOT_CMD(nor_read, 4, 1, do_nor_read, "Read data from NOR Flash", ""); ``` 3. NOR Flash 写入 ```c #include <common.h> #include <command.h> #include <asm/io.h> #include <asm/nor.h> int do_nor_write(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { nor_info_t nor; ulong addr; int len; uchar *buf; /* 解析参数 */ if (argc != 4) return CMD_RET_USAGE; addr = simple_strtoul(argv[1], NULL, 16); len = simple_strtoul(argv[2], NULL, 10); buf = (uchar *)simple_strtoul(argv[3], NULL, 16); /* 初始化 NOR Flash */ nor_init(&nor); /* 写入 NOR Flash */ nor_write(&nor, addr, len, buf); /* 打印写入的数据 */ print_buffer(addr, buf, 16, len / 16 + 1); return 0; } U_BOOT_CMD(nor_write, 4, 1, do_nor_write, "Write data to NOR Flash", ""); ``` 以上代码示例中,假设 NOR Flash 的驱动程序已经在 U-Boot 中实现,并且已经包含在头文件 asm/nor.h 中。nor_info_t 是 NOR Flash 的信息结构体,包含 NOR Flash 的大小、扇区大小、页大小等信息。nor_init() 函数用于初始化 NOR Flash,nor_set_16bit() 函数用于设置 NOR Flash 的模式为 16-bit 模式。nor_read() 函数用于从 NOR Flash 中读取数据,nor_write() 函数用于向 NOR Flash 中写入数据。print_buffer() 函数用于打印读取或写入的数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值