本文主要介绍嵌入式linux设备从裸板到加载bootloader,到启动linux内核和文件系统的大致过程。
先谈谈单片机的启动
接触过硬件知识的同学大概都用过51单片机、stm32等等。但是为什么我们把程序下载进去,然后接通电源程序就可以运行起来?我想这个过程需要我们来思考下。
我们在PC上写好程序然后把程序下载到单片机中一般用的是
串口
,串口只是通俗的说法,在芯片上被称为
uart
(通用异步收发器)或
usart
(通用同步异步收发器),往往呈现在引脚上为RXD,TXD两个引脚,将这两个引脚和地线一起连接到PC的串口即可。但往往现在的笔记本电脑都没有串口了,好在现在有很多串口转USB的芯片(常见的有CP2102、PL2303等等),那么我们需要将单片机U(S)ART的两根脚先连到这块转换芯片上,然后再由转换芯片连接到PC就完成硬件连线了。如下图。
然后在PC端通过下载软件,选择对应的com口就可以将程序下载到芯片中,打开电源程序就可以运行了。可是事实远比表面现象要复杂的多。芯片在我们没有给它烧录程序时它为什么可以进行串口连接并且可以接收PC端发来的程序呢?答案就是芯片在出厂时就携带了一小段程序,这段程序被称为
bootloader
。bootloader一般是固化在芯片0地址或者其它地址(这个地址很重要,需要在下载程序时一打开电源,就跳入到这个地址进行执行程序)的一段程序。这个程序具有一些简单的功能,比如配置芯片的工作频率,配置U(S)ART的波特率,读写存储器等等,正因为这些我们在下载程序时芯片才能够与芯片进行通信并将程序下载到芯片中。所以一般单片机通过串口进行下载程序时会经历下面几步。
- 目标板设置到串口下载模式,往往通过拨码开关或短路帽设置;
- 目标板与PC通过串口线连接;
- PC打开串口,目标板上电,两者握手(通过一些协议确认下载多大程序?什么时候开始?);
- 目标板接收程序,并将程序写入存储器(现在单片机一般是flash)的固定地址;
- 目标板设置到从flash设备中启动,上电后控制器将会把flash中的程序读入ram中的固定地址然后执行。
上面只是单片机下载程序与启动的流程,下面我们再看看嵌入式linux设备是如何进行启动的。
嵌入式linux设备的启动
嵌入式linux设备一般都会携带三大文件,bootloader,Kernel,根文件系统。整体的启动流程就是上电后bootloader将内核拷贝到ram中的固定地址,然后程序(PC指针)跳转到这一地址进行执行,内核启动后将存储在flash上的文件系统的信息结构读入内存,最后执行init程序就完成了linux设备的启动。
可是这些文件又是如何下载进去的呢?在嵌入式linux设备中和单片机类似,但是要稍微复杂点。一般来说一个嵌入式设备的主要电路会像下面一样。
嵌入式设备的芯片往往不称为CPU,而是CPU和一些简单电路构成的MPU,SDRAM(同步动态随机存储器)用来作为内存单元,Nand Flash用来作为数据存储(非易失性),Nor Flash用来作为存储bootloader的存储器。下面简单介绍下这几种存储器。
- SDRAM,一种DRAM(动态随机存储),相对于SRAM(静态随机存储)。DRAM结构简单由一个晶体管和一个电容构成,但是由于电容会不断放电,所以需要周期性的充电,也就是所谓的刷新,现在的MPU都会自带SDRAM控制器进行刷新;SRAM结构一般由六个晶体管构成,不需要周期刷新只需要供电就可以保持数据。因为DRAM中含有电容所以造成体积较大,但是需要晶体管少价格相对SRAM便宜。所以SRAM一般会用在CPU和一些存储设备间作为Cache使用集成进微控制器,DRAM作为片外内存使用。
- Nor Flash,一种存储设备。存在地址总线和数据总线,所以可以进行随机存储(该特点决定这种存储器可以运行程序)。但是运行程序速度较慢,一般会用来存储bootloader。
- Nand Flash,一种存储设备。没有地址总线,只有数据总线和一些命令总线,所以外部的引脚数量较少。较小体积可以存储很大的容量,1Gb、2Gb容量很普遍。
正是因为这些存储器具有不同的特点,所以在嵌入式设备中扮演不同的角 {MOD}。下面谈谈嵌入式芯片的启动过程。
一般来说嵌入式芯片会有启动的选项,这些选项是由引脚决定,是从0地址启动,还是由
step stone
启动。
- 0地址启动指的是CPU PC指针直接取地址总线上的0地址上的指令运行,所以地址总线的0地址必须连接着可以地址访问的存储器,SDRAM或Nor Flash,但是一开始上电SDRAM中是不可能有指令的(易失性存储),所以0地址线在嵌入式设备中连接的往往是Nor Flash。
- step stone启动方式指的是芯片一上电,它会自动地去通过Nand Flash控制器、USB控制器等等去读出一段程序(往往是4KB),加载到一个Ram(大小很小,芯片自带的,一般也是4KB)中运行。
内核一般不能直接运行,运行之前需要配置基本的硬件环境,所以芯片首先需要运行的程序就是bootloader。由上面的启动方式我们可以看出bootloader要么放在Nor Flash中,从Nor Flash上电运行;要么可以通过step stone:在存储器中写上一段代码,这段代码小于4KB,但是可以初始化硬件,并将bootloader由存储器拷贝到内存,并跳转到带内存地址执行。这样无论怎么样,bootloader都可以得到运行。
那么问题来了,上面提到的代码怎么写到Nor Flash中?可以通过JTAG进行!但是无论怎么样,bootloader都需要先存在在Nor Flash中,否则无法将程序直接写入存储器。通过step stone也需要Nor FLash的bootloader将上述的拷贝程序写入对应的存储器。
bootloader一旦启动完成,万事皆可通过bootloader进行。比如可以通过bootloader将内核和文件系统写入Nand Flash,下次启动时bootloader自动将内核拷贝到SDRAM去执行,然后拉起整个操作系统。至于从哪里获取内核,这个取决你的bootloader功能够不够强大,可以让bootloader联网通过FTP或TFTP拷贝,可以让bootloader通过存储卡拷贝,通过串口下载等等。
至此,嵌入式linux设备的上电启动就这样结束啦,U-boot启动流程有时间再整理下~