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 with-board=mba-44b0-with-linux-prefix=/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 所列为不同的外部数据总线宽度下,处理器与外部存储器的地址线接法。
表1 存储器在不同总线宽度下与S3C44B0 地址线的接法
存储器地址引脚 | 8 位数据总线时S3C44B0 引脚 | 16 位数据总线时 S3C44B0 引脚 |
32 位数据总线时 S3C44B0 引脚 |
A0 | A0 | A1 | A2 |
A1 | A1 | A2 | A3 |
A2 | A2 | A3 | A4 |
A3 | A3 | A4 | A5 |
…… | …… | …… | …… |
对Flash 编程需要对Flash 写入一个特定的时序。如果S3C44B0 寻址0x5555,由于外部总线错了一位,这样在Flash 看来发过来的地址信号是0xAAAA ,也就不能正确地完成操作。注意到这一点,根据Blob 自带的Flash驱动程序,就可以很方便地改写出适合自己Flash 驱动程序。
结语
根据笔者经验介绍了Blob 在S3C44B0 上的移植,目前它已经能稳定地运行在开发板上;并且可以进行烧写Flash,查看内存,引导uClinux 等操作,为项目的后续开发奠定了良好的基础。