(1)start.s
.globl _start @指定标号_start为globl型, 外部可调用
_start: @定义_start标号,gnu编译器默认程序入口
ldr r1, =0xE0200280 @将 GPJ2CON寄存器地址号写入r1
// 设置CBT-Tiny210 板载LED连接到GPJ4端口,需要修改寄存器地址
ldr r1, =0xE02002c0 @GPJ4CON寄存器地址
ldr r0, =0x00001111 @将配置字0x00001111写入r0
str r0, [r1] @配置字写入GPJ2CON寄存器
mov r2, #0x1000 @赋值 r2=1000,用于定义循环次数
led_blink:
ldr r1, =0xE0200284 @GPJ2DAT寄存器端口地址
ldr r1, =0xE02002c0 @GPJ4DAT寄存器地址
mov r0, #0
str r0, [r1] @写入0,点亮LED
bl delay @调用延时函数
ldr r1, =0xE0200284
ldr r1, =0xE02002c0 @GPJ4DAT寄存器地址
mov r0, #0xf
str r0, [r1] @写入1,熄灭LED
bl delay @调用 延时函数
sub r2, r2, #1 @r2 = r2-1
cmp r2,#0 @亮/灭过程执行了1000次
bne led_blink @少于1000次,跳转到led_blink处继续执行
halt: @定意标号
b halt @跳转到halt,死循环
delay: @定义延时函数
mov r0, #0x100000 @延时时间,可尝试改为0x400000
delay_loop:
cmp r0, #0
sub r0, r0, #1
bne delay_loop
mov pc, lr @函数返回,适用于bl指令调用。lr存有调用处的断点。
(2)Makefile
1 led.bin: start.o
2 arm-linux-ld -Ttext 0x0 -o led.elf $^
3 arm-linux-objcopy -O binary led.elf led.bin
4 arm-linux-objdump -D led.elf > led_elf.dis
5 gcc mkv210_image.c -o mkmini210
6 ./mkmini210 led.bin 210.bin
7 %.o : %.S
8 arm-linux-gcc -o $@ $< -c
9 %.o : %.c
10 arm-linux-gcc -o $@ $< -c
11 clean:
12 rm *.o *.elf *.bin *.dis mkmini210 -f
在1.leds_s 目录下执行make命令,编译系统按以下顺序执行编译链接操作:
1不执行行号1-4:此时无.o文件。
2执行行号5:使用gcc编译gcc mkv210_image.c文件,生成可执行文件mkmini210。
3不执行行号6:此时无led.bin文件。
4执行行号7,8:使用arm-linux-gcc将当前目录下的汇编文件(.s)编译成.o文件。
5执行行号9,10:使用arm-linux-gcc将当前目录下的C文件(.c)编译成.o文件。
6执行行号2:将所有.o文件链接成elf格式文件。由于程序代码与位置无关,能在任何一个地址上运行。这里通过-Ttext 0x0指定程序运行地址是0x0。
7执行行号3:将elf文件抽取为可在ARM开发板上运行的led.bin文件。
8执行行号4:将elf文件反汇编后保存在dis文件中,供调试程序时用。
9执行行号6:运行mkmini210处理led.bin文件,处理结果是在led.bin中添加16字节头文件后生成210.bin文件。
10执行行号11,12:清除编译过程文件
(3)mkv210_image.c
上电复位开始,S5PV210会先运行内部IROM中的固化代码进行一些必要的初始化。执行完后依赖硬件上设置的启动条件,会自动读取NandFlash或SD卡等启动设备存储BL1的前16K程序代码并复制到ISRAM中,这16K代码的前16byte中保存了一个校验和的值。复制代码过程中S5PV210会用同样方法生成一个校验和,并与add_data比较,如果相等认为复制结果正确,才可在ISRAM中运行所复制的代码,否则S5PV210将停止运行程序代码。
所有在S5PV210上运行的BL1文件都必须具有一个16byte的文件头,该16byte中需包含校验和信息。mkv210_image.c由友善之臂开发板技术交流社区arm9论坛上的网友提供,其作用是来给经过编译的原始BL1文件添加头信息。
mkv210_image.c的核心工作如下:
第一步 分配16k的buffer;
第二步 将led.bin读到buffer的第16byte开始的地方;
第三步 计算校验和,并将校验和保存在buffer第8~11byte中;
第四步 将16k的buffer拷贝到210.bin中。
16byte头文件格式及校验方法详见参见第2章的启动过程一节。
参考手册:
S5PV210_iROM_ApplicationNote_Preliminary_20091126.pdf
S5PV210_UM_REV1.1.pdf
(4)write2sd
SD卡起始扇区为0,一个扇区的大小为512byte。当设定为SD卡启动模式后,IROM里的固化程序代码从扇区1开始复制代码,所以将可执行文件210.bin事先烧写到SD卡起始为1扇区的位置。write2sd是一个脚本文件,用于将指定文件烧写到SD卡。
write2sd文件内容:
#!/bin/sh
sudo dd iflag=dsync oflag=dsync if=210.bin of=/dev/sdb seek=1
dd:读写命令。
210.bin:指定烧写的文件名。
if:是输入。
of:是输出。
/eek=1:表示从扇区1开始读写。
/dev/sdb:SD卡设备在宿主机Linux环境下的挂载点。只有当系统识别出SD卡设备并成功挂载后,才可以使用write2sd脚本文件进行烧写工作。可以通过fdisk命令查看SD卡的挂载点。一般情况下SD卡设备会挂载到Linux环境/dev/sdb下,若是挂载到Linux环境下其它位置,需要调整write2sd文件内容。
[root@localhost 1.leds_s]# fdisk –l
Device Boot Start End Blocks Id System
/dev/sdb1 20 240 1766400 b W95 FAT32
Partition 1 has different physical/logical endings:
phys=(238, 254, 63) logical=(239, 39, 56)