上一篇文章使用crosstool-NG创建了新的linux-gnueabi工具链。本文使用新的工具链创建第一个运行在s3c2440上的程序。
首先创建toolchains.sh,并将该脚本source到当前shell,这样就可以直接使用了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26  | #!/bin/sh#TOOLCHAIN_DIR=/work/toolchain/gcc-3.4.5-glibc-2.3.6#TOOLCHAIN_PREFIX=arm-linuxTOOLCHAIN_DIR=/work/toolchain/arm-unknown-linux-gnueabiTOOLCHAIN_PREFIX=arm-unknown-linux-gnueabiTOOLCHAIN_BIN_PREFIX=${TOOLCHAIN_DIR}/bin/${TOOLCHAIN_PREFIX}CC=${TOOLCHAIN_BIN_PREFIX}-gccAS=${TOOLCHAIN_BIN_PREFIX}-asCPP=${TOOLCHAIN_BIN_PREFIX}-cppLD=${TOOLCHAIN_BIN_PREFIX}-ldSTRIP=${TOOLCHAIN_BIN_PREFIX}-stripOBJDUMP=${TOOLCHAIN_BIN_PREFIX}-objdumpOBJCOPY=${TOOLCHAIN_BIN_PREFIX}-objcopyREADELF=${TOOLCHAIN_BIN_PREFIX}-readelfRANLIB=${TOOLCHAIN_BIN_PREFIX}-ranlibSIZE=${TOOLCHAIN_BIN_PREFIX}-sizeSTIRNGS=${TOOLCHAIN_BIN_PREFIX}-stringAR=${TOOLCHAIN_BIN_PREFIX}-arNM=${TOOLCHAIN_BIN_PREFIX}-nmADDR2LINE=${TOOLCHAIN_BIN_PREFIX}-addr2lineexport CC AS CPP LD STRIP OBJDUMP OBJCOPY READELF RANLIB SIZE STRINGS AR NM ADDR2LINE | 
需要具备汇编相关的知识,可参考我之前的文章。start.S准备入口,提供_start符号。
1 2 3 4 5 6 7 8 9 10  |     .text    .global _start_start:    ldr r0, =0x53000000    mov r1, #0    str r1, [r0]  @ disable watchdog    ldr sp, =1024*4    bl mainloop:    b loop | 
这个汇编文件干2件事情:关看门狗;设置栈,跳转到main执行。编译方法:
1  | $(AS) -o start.o start.S | 
main函数,进行跑马灯操作,就是循环设置LED的GPIO寄存器,这里用c实现最简单。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35  | /* * my s3c2440 develop board has 4 led * led1 ==> GPF4 * led2 ==> GPF5 * led4 ==> GPF6 * led8 ==> GPF7 */#define GPFCON      (*(volatile unsigned long *)0x56000050)#define GPFDAT      (*(volatile unsigned long *)0x56000054)#define GPF4_out    (1<<(4*2))#define GPF5_out    (1<<(5*2))#define GPF6_out    (1<<(6*2))void main(){    int i = 0, j = 4;    // configure gpio as output mode    GPFCON = GPF4_out | GPF5_out | GPF6_out;    while (1)    {        i++;        if (i == 30000) {            GPFDAT = ~(1 << j);            j++;            if (j == 7)                j = 4;            i = 0;        }    }} | 
编译:
1  | $(CC) -c -o led.o led.c | 
使用自定义的简单链接脚本,需要具备ld相关的知识,可参考本站ld分类中的文章。
1 2 3 4 5 6  | SECTIONS{    . = 0;    .text : { *(.text) }    .data : { *(.data) }} | 
定义链接地址从0开始,因为编译出的binary放在NAND的首4K处,被拷贝到内部SRAM,从地址0开始执行。此处链接器会将_start入口放在.text段的最前面。
链接:
1  | $(LD) T bare.lds -o led_elf start.o led.o | 
链接生成的led_elf是ELF格式文件,包括ELF头等信息,需要有辅助程序(loader)才能运行,所以需要使用objcopy工具生成二进制文件。objcopy的工作是把.text和.data段抽出,这样CPU就可从.text最开始处开始执行,不需要别人的帮助。
1  | $(OBJCOPY) -O binary -S led_elf led_bin | 
将led_bin烧录到s3c2440的nand,重启切换到nand启动,可以看到3个LED开始轮流亮。