关于Blob的介绍及其在S3C44B0上的移植

bootloader对于嵌入式设备来说至关重要,它涉及到许多硬件相关的知识。对于自制的嵌入式开发板,它又是不可跳过的步骤,所以很多人对于它感到很头痛。本文将以一款优秀的bootloader blob为例,详细讲解它的运行原理以及在s3c44b0通用处理器上的移植过程,为在嵌入式设备上的后续软件开发打下基础 。
1 blob简介
blob是boot loader object的缩写,是一款功能强大的bootloader。它遵循gpl,源代码完全开放。blob既可以用来简单的调试,也可以启动linux kernel。blob最初是jan-derk bakker和erik mouw为一块名为lart(linux advanced radio terminal)的板子写的,该板使用的处理器是strongarmsa-1100。现在blob已经被移植到了很多cpu上,包括s3c44b0。
mba44b0是一款基于s3c44b0的开发板。本文将以运行在mba44b0开发板上的blob的源代码为基础,再针对自己的开发板进行blob的移植。
开发板的主要配置为:
◇三星arm7处理器s3c44b0;
◇2mb的flash,地址范围0x0000 0000~0x0020 0000;
◇8mb的sdram,地址范围0x0c00 0000~0x0c80 0000;
◇1个串口,2个led灯;
◇jtag接口;
◇晶振为6mhz,系统主频为60mhz。
2 blob的运行过程分析
图1为blob程序启动流程。
blob编译后的代码定义最大为64kb,并且这64kb又分成两个阶段来执行。第一阶段的代码在start.s中定义,大小为1kb,它包括从系统上电后在0x00000000地址开始执行的部分。这部分代码运行在flash中,它包括对s3c44b0的一些寄存器的初始化和将blob第二阶段代码从flash拷贝到sdram中。除去第一阶段的1kb代码,剩下的部分都是第二阶段的代码。第二阶段的起始文件为trampoline.s,被复制到sdram后,就从第一阶段跳转到这个文件开始执行剩余部分代码。第二阶段最大为63kb,单词trampoline词义为“蹦床”,所以在这个程序中进行一些bss段设置,堆栈的初始化等工作后,最后跳转到main.c进入c函数。
我们的移植主要需要对上述的几个文件进行修改。在进行移植以前,首先需要对存储器的地址空间分配了解清楚。关于存储器空间的定义在/include/ blob arch/mba44b0.h中。
图2为在flash中的存储器空间分布,图3为启动后在sdram中的存储器空间分布。
如图2所示,2mb的flash空间分别分配给了blob、kernel、ramdisk。系统上电后,先执行第一阶段代码,进行相应的初始化后,将blob第二阶段代码复制到ram地址blob_abs_ base,然后跳转到第二阶段开始执行。
在第二阶段中,从汇编跳转到c的main()函数,继续进行如下工作:
◇外围的硬件初始化(串口,usb等);
◇从flash中将kernel加载到sdram的kernel区域;
◇从flash中的ramdisk加载到sdram的ramdisk区域;
◇根据用户选择,进入命令行模式或启动kernel。
在我们使用的开发板上,kernel选用uclinux。由于flash的存储空间有限,所以存放在flash中的uclinux内核是经过压缩的。blob将压缩的uclinux内核加载到sdram地址0x0c300000。如果选择启动uclinux,那么压缩的uclinux内核将自解压.text段到0x0c00800(见uclinux/arch/armnommu/makefile),然后再跳转到该处,开始运行uclinux。具体的uclinux移植在此就不详细讨论了。
在sdram的存储器空间分配图中,可以看到有blob_base和blob_abs_base两部分。blob_abs_base大家已经知道了,是blob将自身的第二阶段代码复制到sdram所在的区域,而blob_base则是从blob进行自升级或调试的区域。举例说明,假如blob已经能正常运行了,但是对于flash的擦写还不能支持得很好,就可以使用已经运行的blob通过串口将新编译好的blob下载到sdram中该区域进行运行调试。调试通过后,可以通过blob烧写进flash,覆盖原来的blob进行升级。这样就不必因为对blob做了一点小的改动就重新烧写flash,从而减少了烧写flash的次数。
3 blob的移植
对blob的运行有了一定了解后,就可以进行blob的具体移植了。首先要修改的是start.s文件,具体工作如下:
◆ 屏蔽掉看门狗wtcon;
◆ 配置寄存器syscfg暂时关闭缓存,等blob运行稳定后再开启提高性能;
◆ 初始化i/o寄存器;
◆ 屏蔽中断;
◆ 配置pllcon寄存器,决定系统的主频;
◆ 调用ledasm.s,在串口未初始化时led状态对于程序是否正常运行很重要;
◆ 调用memsetup-s3c44b0.s中的memsetup进行初始化存储器空间,初始化sdram刷新速率等;
◆ 将第二阶段复制到sdram,并且跳转到第二阶段。
在ledasm.s中,提供了led的汇编的语言驱动程序。在blob还有个led.c文件,它和ledasm.s原理一样,只不过是在c语言中调用的。修改led是为了方便初期阶段的调试。在这里根据自己的开发板进行修改。
在memsetup-s3c44b0.s中,修改memory_config中设置存储器相关的配置,并设定sdram刷新速度,相关源码如下所示:
memory_config:
.long 0x11101002 /*进行存储器的配置,
sdram刷新速度配置等*/
… /*这里需要根据不同情况进行修改*/
.long 0x20
.globl memsetup /*定义全局标号,以便能被start.s调用*/
memsetup:
ldr r0, =memory_config /*进行配置*/
ldmia r0, {r1-r13}
ldr r0, =0x01c80000
stmia r0, {r1-r13}
mov pc, lr /*程序返回*/
trampoline.s不需要进行修改。
进入main()后,串口传输速度在结构体blob_status中设定:
blob_status.downloadspeed = baud_115200;
blob_status.terminalspeed = baud_115200;
串口的初始化相关代码定义在函数s3c44b0_serial_ init()中,该函数在serial-s3c44b0.c中。对于s3c44b0的串口,一般只需要初始化下面四个寄存器串口就可以正常工作。如果不能工作,可能是系统时钟设置不同,只需要按照下列公式计算出divisor:
divisor=(int)(mclk/(baud ×16))-1
替换下面的divisor即可。其中mclk为系统主频,baud为波特率。
/*serial-s3c44b0.c中s3c44b0_serial_init()函数初始化串口0部分*/
reg(ufcon0) = 0x0; /*关闭fifo*/
reg(ulcon0) = 0x03; /*设置数据位8,无奇偶校验,1位
停止位*/
reg(ucon0) = 0x05; /*脉冲中断,中断请求或查询模式*/
reg(ubrdiv0) = divisor;/*设置波特率*/
至此,初级移植工作已经完成,运行./configure 杦ith-board=mba-44b0-with-linux-prefix=http://www.eda-china.com/path/to/linux-src进行相关配置。在此还可以加一些开关选项进行配置,具体请参阅blob自带文档。如果没有错误,就可以make进行编译了。如果编译正确,可在blob/src/blob下得到bin格式的blob,将其烧写到flash即可运行。关于blob第一部分和第二部分的链接脚本,可以在start-ld-script和rest-ld-script.in中看到相关的链接地址,编译器是根据这些地址链接程序的。在blob/src/blob/makefile中可以看到,两个阶段分别以blob-start和blob-rest来编译,最后通过dd命令将它们组成一个完整的blob二进制文件。
(1)命令行的修改
在笔者使用的blob版本中,backspace不能起作用,这对于调试非常的不方便。查阅源码,可以发现在src/blob/lib/command.c中,getcommand函数中定义着人机交互部分。将else if(c ==’b’这一行修改为else if(c ==0x7f),即可支持backspace功能。
(2)blob的运行
如果在前面的工作中没有什么问题的话,将blob/src/blob/blob文件烧写进flash后,上电就可以从串口看到欢迎信息。加载linux内核和文件系统的后,等待几秒,如果没有操作,将启动操作系统,否则出现提示符:
blob>
表示进入blob。在该模式下提供了许多命令,可以方便地进行硬件调试、系统升级和系统引导。
blob常用的命令有:blob、boot、xdownload、flashreload、dump、reblob、status等。
不同的flash操作有所不同。笔者发现通过blob烧写flash的软件有些问题,为了调试方便,决定编写自己的flash驱动程序。
(3)flash驱动程序的编写
flash作为非易失性的存储器,在开发板上的作用是能保存数据且掉电不丢失。和eeprom最大的不同在于,对flash编程不需要对特定的引脚加高电压,只是对特定地址写入一组特定的数据即可进行编程,这样就直接在开发板上通过软件进行擦写,不必使用特定的编程器。但是它的缺点也是很明显的:操作过于复杂,sst39vf160是sst公司的一款16m位的flash,16位数据线宽度,共2mb容量,分为512个扇区,每个扇区有4kb,或32个块(block),每个块64kb。对flash编程之前,必须对相应的扇区、块或者整个芯片进行擦除后,才能进行编程。
通过s3c44b0进行flash的烧写需要注意几点:首先,s3c44b0外部地址总线是根据外部数据总线宽度连接的。例如,本开发板外部数据总线为16位宽度,这样s3c44b0的地址线a0就没有接入外部地址总线,而是从a1接起。表1所列为不同的外部数据总线宽度下,处理器与外部存储器的地址线接法。
对flash编程需要对flash写入一个特定的时序。如果s3c44b0寻址0x5555,由于外部总线错了一位,这样在flash看来发过来的地址信号是0xaaaa,也就不能正确地完成操作。注意到这一点,根据blob自带的flash驱动程序,就可以很方便地改写出适合自己flash驱动程序。
结 语
根据笔者经验介绍了blob在s3c44b0上的移植,目前它已经能稳定地运行在开发板上;并且可以进行烧写flash,查看内存,引导uclinux等操作,为项目的后续开发奠定了良好的基础。

利用NFC技术来实现LED驱动电源的可编程技术
激光雷达为自动驾驶的落地起到了极为重要的作用
无线传感器网络节点数据短距离接收研究
轻薄移动电源什么牌子好?超轻薄的移动电源推荐
应该了解300 CPU MPI全局数据通讯组态的方法
关于Blob的介绍及其在S3C44B0上的移植
小米Note2、乐Max2、ZUK_edge、酷派S1:这四款手机入手时需慎重考虑,性价比并不是很值!
探寻手机里那些不为人知的闪光功能 京东金机奖评选温情启动
应急照明控制器如何进行智能控制和远程管理
2020年的工业机器人行业或将进入调整期
单模光纤的优缺点
高精度红蜡3D打印加工服务
半导体三极管的分类
华润微发布2019年年报和2020年一季报
一文看透工业领域ChatGPT 的应用
如何选择服务器,高防服务器的租用技巧
华硕发布新笔记本 ZenFone 6相机评分出炉
高功率LED的封装基板有哪些种类?
因代码不规范,程序员枪击4名同事,一个用生命维护代码的程序员
数据的护城河,湖泊和海洋,去中心化数据交换可以有哪些帮助?