上一篇文章使用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-linux TOOLCHAIN_DIR= /work/toolchain/arm-unknown-linux-gnueabi TOOLCHAIN_PREFIX=arm-unknown-linux-gnueabi TOOLCHAIN_BIN_PREFIX=${TOOLCHAIN_DIR} /bin/ ${TOOLCHAIN_PREFIX} CC=${TOOLCHAIN_BIN_PREFIX}-gcc AS=${TOOLCHAIN_BIN_PREFIX}-as CPP=${TOOLCHAIN_BIN_PREFIX}-cpp LD=${TOOLCHAIN_BIN_PREFIX}-ld STRIP=${TOOLCHAIN_BIN_PREFIX}-strip OBJDUMP=${TOOLCHAIN_BIN_PREFIX}-objdump OBJCOPY=${TOOLCHAIN_BIN_PREFIX}-objcopy READELF=${TOOLCHAIN_BIN_PREFIX}-readelf RANLIB=${TOOLCHAIN_BIN_PREFIX}-ranlib SIZE=${TOOLCHAIN_BIN_PREFIX}-size STIRNGS=${TOOLCHAIN_BIN_PREFIX}-string AR=${TOOLCHAIN_BIN_PREFIX}-ar NM=${TOOLCHAIN_BIN_PREFIX}-nm ADDR2LINE=${TOOLCHAIN_BIN_PREFIX}-addr2line export 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 main loop: 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开始轮流亮。