ILD

first binary run on s3c2440
作者:HerbertYuan 邮箱:yuanjp89@163.com
发布时间:2017-9-18 站点:Inside Linux Development

上一篇文章使用crosstool-NG创建了新的linux-gnueabi工具链。本文使用新的工具链创建第一个运行在s3c2440上的程序。


1 toolchain

首先创建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


2 start.S

需要具备汇编相关的知识,可参考我之前的文章。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


3 led.c

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

4 bare.lds

使用自定义的简单链接脚本,需要具备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


5 objcopy

链接生成的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开始轮流亮。


Copyright © linuxdev.cc 2017-2024. Some Rights Reserved.