嵌入式Linux系列第3篇:uboot编译下载
1.引言
本篇介绍如何编译及下载uboot到ARM板子上。对于初学者有这么三个名词,分别是uboot、kernel和rootfs。这三个名词我刚开始接触是非常的困惑,现在随着使用增多稍微有一点点感觉。大家刚开始学不用太纠结这个问题,等实际操作一段时间就会理解了。uboot的主要作用是用来启动linux内核,因为CPU不能直接从块设备(如NAND/EMMC/SD卡)中执行代码,需要把块设备中的程序复制到内存中,而复制之前还需要进行很多初始化工作,如时钟、串口等;要想让CPU启动linux内核,只能通过另外的程序,进行必要的初始化工作,再把linux内核中代码复制到内存中,并执行这块内存中的代码,即可启动linux内核;一般情况下,我们把linux镜像储存在块设备中如SD卡、Nandflash等块设备中,首先执行uboot代码,在uboot中把块设备中的内核代码复制到某内存地址处,然后再执行这个地址,即可启动内核。
2.官方资料下载
针对某一款具体的芯片,我建议从该芯片原厂那里拿到官方的资料,因为官方的资料会不断的更新同时也更有权威性,NUC972的官方bsp资料位于github.com/OpenNuvoton/ARM7-ARM9-Family
我们先把Uboot下载下来,最简单的方法就是直接点击Clone or download - Download Zip文件。
3.Uboot编译
步骤1:在虚拟机~/nuc972 目录下,新建uboot文件夹
步骤2:将windows下载的NUC970_U-Boot_v2016.11-master.zip 放到虚拟机上述目录
步骤3:解压NUC970_U-Boot_v2016.11-master.zip文件
步骤4:进入到NUC970_U-Boot_v2016.11-master目录,编译前先source /home/topsemic/nuc972/toolchain/environment.sh
输入make,先编译下试试,提示以下错误:
make:arm-linux-gcc:命令未找到
我们要看下Makefile,原因是Makefile中CROSS_COMPILE设置的问题,需要修改下,改成我们装的交叉编译链,
再次编译,提示如下错误:
提示我们没有.config 文件,让我们输入make oldconfig 或者make menuconfig 或者make xconfig
我们先make menuconfig 试试,输入make menuconfig,又提示错误了
我们上网查一下,是缺少libncurses5-dev库的原因,安装一下,
sudo apt-get install libncurses5-dev,
再一次输入make menuconfig,过一会弹出了如下界面:
这就表示make menuconfig执行成功了。
这是一个图像化的配置界面,可以用来配置uboot里的各种参数。我们使用键盘方向键向右移动到Save,按Enter键我们先保存下试试。
在下图弹出的OK上按Enter键保存
再Exit就行了
最后Exit即可。这样就生成了.config文件。
注意.config 文件是个隐藏文件(以.开头的都是隐藏文件),需要ls -a 才能看到
这时再次输入make
又提示了错误, 我们猜测可能是config文件不对,我们用nuc972相关的配置,输入make nuc970_defconfig,其实这个nuc970_deconfig是个文件,在configs目录中,打开看下,里面就是一些配置选项。关于uboot里这些参数的定义,大家可以参考《NUC970 Linux BSP User Manual CHT.pdf》4.1节介绍。
再次make,成功,生成u-boot.bin(在uboot根目录下)和u-boot-spl.bin(uboot 根目录的spl文件夹里)
关于uboot的详细启动过程,大家也可以上网查阅资料了解。
4.烧写Uboot
既然已经成功编译uboot,那么我们烧写到板子里看看能否运行吧。烧写前准备工作:
在Windows上线安装WinUSB4NuVCOM_NUC970.exe,这是一个驱动,具体安装步骤参考《NUC970 Linux Quick Start Guide CHT.pdf》中3.1节介绍,此文档在百度网盘里。
1)板子上会有跳线帽或者拨码开关,将其置于usb下载模式,连接usb到电脑,给板子上电
2)打开NuWriter.exe,
因为我的板子里原来有uboot,kernel,文件系统,我先Erase一下:
3)将上面生成的u-boot-spl.bin放进来
烧录成功后显示:
再烧录uboot.bin
4)将跳线帽或者拨码开关切换回NAND 运行模式,上电,
连接上调试串口输出以下信息:
5.结束语
本篇介绍了uboot的编译和烧写,uboot的编译方法和传统的MCU编译有很大的区别,需要大家熟悉一下。
有问题欢迎大家留言讨论。
下期会给大家介绍kernel相关内容。
海思Hi35xx uboot启动分析总结
liwen01 2019.12.09
前言
在嵌入式linux设备中,uboot的最终目的就是启动kernel。对于uboot而言,没有人把它引导起来,所以uboot首先需要把自己加载起来,然后再去引导kernel的启动,这也就可以大致的分为Uboot启动的第一阶段和第二阶段。
(一)start.S第一阶段启动总结
在海思hi3251a官方的《Hi3521A_PINOUT_CN》手册上有上电锁存管脚BOOTROM_SEL,这个是引脚用来定义是从BOOTROM启动还是从spi flash启动 。
(1)BOOTROM启动
当启动模式为从 BOOTROM 启动时,海思的BOOTROM的程序会去初始化串口,然后与海思的HiBurn工具建立通信
如果能建立通信,则启动HiBurn升级uboot程序流程,如果不能与HiBurn建立连接,等待一段时间之后它就转去从外部的spi flash启动
(2)HiBurn 烧入原理
HiBurn烧入的基本原理是,HiBurn工具与BOOTROM程序建立连接之后,先下载uboot程序的开始4KB数据到海思芯片的内部RAM
然后通过下载的那一小部分uboot代码去初始化外部的DDR,如果DDR初始化成功,HiBurn再将剩下的uboot程序下载到外部的DDR中去
最后是在DDR中启动uboot,如果要进行烧入操作,是通过DDR中的Uboot程序,发送uboot命令将DDR中的uboot程序烧入到外部的flash中去,这样就实现了uboot程序的升级。
(3)spi flash启动
海思的hi3521a芯片支持从 SPI NOR Flash 和 SPI NAND Flash 直接启动,它的启动也就是我们start.s中的大部分实现。主要做的工作有:
初始化CPU相关功能(关缓存,关MMU,设置SVC模式等)将异常中断向量表重定向到内部RAM将uboot代码重定向到外部DDR中设置栈空间清空BSS段最后调用C语言接口去执行C语言代码实现第二阶段的启动。第一阶段在执行之后,在DDR中的映射空间的数据分布如下:(二)start_armboot第二阶段启动总结
在uboot的启动的第二阶段,主要做的是:
初始化变量和结构体重定向环境变量初始化堆管理器初始化环境变量进入命令处理循环在命令处理循环中,默认Uboot是超时等待用户命令输入
如果有检测到命令的输入,则执行相应的命令,如果超时没有命令输入,uboot默认执行的bootm命令进行kernel启动引导。
这里涉及到两个比较总要的点:环境变量的重定向和uboot命令处理。
(1)环境变量重定向
在uboot第二阶段的时候,uboot会去检测flash中环境变量的地址中环境变量是否有效,如果有效,则使用flash中的环境变量值来初始化uboot运行中的环境变量,如果flash中的环境变量无效,则使用默认的环境变量来初始化运行中的uboot。
在uboot的用户命令操作过程中,如果有对环境变量进行修改,都是修改的内存中的那一份环境变量,如果要将修改的环境变量保存到flash中去,则需要运行命令saveenvuboot在flash的分布如下:
uboot.bin烧入到flash的0地址位置,boot.bin里面的数据就是按我们连接脚本中的数据那样分布。在0x80000(512KB)开始的位置就是环境变量的在flash的位置,其大小为256KB。
(2)uboot命令处理
在启动的最后阶段,就是执行uboot的bootm命令,主要就是uboot将kernel程序从flash中复制到内存去,然后就是检验kernel镜像文件的有效性,设置uboot传递给kernel的参数,设置kernel启动的环境(比如关缓存,关中断,CPU处于SVC模式等)
最后就是通过一个函数指针指向kernel的启动地址,调用该函数实现uboot到kernel的运行。
在这个过程中,启动参数和机器码同时传递给kernel,关于参数传递,实际在这里是通过寄存器间参数的地址传递给了kernel。
(3)参数传递
C语言进行函数调用的时候,常常会传递给被调用的函数一些参数,对于这些C语言级别的参数,被编译器翻译成汇编语言的时候,就要找个地方存放一下,并且让被调用的函数能够访问,否则就没发实现传递参数了。对于找个地方放一下,分两种情况。
一种情况是,本身传递的参数就很少,就可以通过寄存器传送参数。因为在前面的保存现场的动作中,已经保存好了对应的寄存器的值,那么此时,这些寄存器就是空闲的,可以供我们使用的了,那就可以放参数,而参数少的情况下,就足够存放参数了,比如参数有2个,那么就用r0和r1存放即可。另外一种情况是,如果参数太多,寄存器不够用,那么就得把多余的参数堆栈中了。即,可以用堆栈来传递所有的或寄存器放不下的那些多余的参数。--------------End--------------
如需获取更多内容
请关注公众号 liwen01
相关问答
怎么样把路由器里的固件拷贝出来-ZOL问答ng1997需要先将固件包拷贝到文件管理--U盘/手机存储/根目录上面,然后再按照固件升级的方法进行操作,进入官网首页社区--板块--v粉玩机--玩机技巧--搜索“官网固...
U盘的内容怎么看不到了? - 懂得找对人了,我刚解—文件夹选项藏受保护的系统文件上的勾去掉,再在显示所有文件和文件夹上点上点。所有东西就都出来了,然后你把U盘的东西复制出来,格...
求用U盘从电脑上下电视剧到电视机上看,该怎么样下,是什么格式...到网站下载需要的电影,移到U盘在插到电视格式参照你的电视支持的格式不对,转码到mp4格式应该就行了可以下个360手机助手U盘插电脑上,在电脑上打...
淘欢q9网络机顶盒刷机包下载-ZOL问答有没有无线网卡啊关键还要你的系统支持无线。可以到ZNDS论坛找找看,我之前就是在这个论坛找的刷机包还有教程于这个问题;至于安装的方法原则上都...
夏新L6机顶盒刷机用什么刷机包-ZOL问答将要刷的版本卡刷完整包用手机下载或用电脑端下载后复制到手机。三、系统更新...二、将要刷的版本卡刷完整包用手机下载或用电脑端下载后复制到手...