如何编译代码并将其烧写到ARM开发板:从源代码到可执行文件的完整流程
在嵌入式开发中,编译代码并将其部署到目标硬件是一个核心过程。本文将详细介绍如何使用交叉编译工具链将源代码编译为可执行文件,并最终烧写到ARM开发板(以I.MX6U为例)的SD卡中运行。以下内容将分为编译过程、Makefile创建以及代码烧写三个部分。
一、编译程序的四个步骤
编译一个能在ARM开发板上运行的程序,通常需要以下步骤:
- 使用
arm-linux-gnueabihf-gcc
编译源文件
将.c
或.s
文件编译为目标平台的.o
目标文件。 - 链接生成ELF文件
使用arm-linux-gnueabihf-ld
将多个.o
文件链接为一个ELF格式的可执行文件。 - 转换为BIN文件
使用arm-linux-gnueabihf-objcopy
将ELF文件转换为适合烧写的.bin
文件。 - 反汇编查看汇编代码
使用arm-linux-gnueabihf-objdump
将ELF文件反汇编为汇编代码,便于调试。
下面我们以一个简单的led.s
汇编文件为例,逐步讲解。
二、详细编译流程
1. 使用arm-linux-gnueabihf-gcc
编译文件
为了在ARM开发板上运行程序,我们需要使用交叉编译器arm-linux-gnueabihf-gcc
。假设我们有一个led.s
汇编文件,编译命令如下:
arm-linux-gnueabihf-gcc -g -c led.s -o led.o
-g
:生成调试信息,方便后续用GDB调试。-c
:仅编译源文件,不进行链接。-o
:指定输出文件名,这里将led.s
编译为led.o
。
执行后,当前目录下会生成led.o
文件。
2. 使用arm-linux-gnueabihf-ld
链接文件
编译得到的.o
文件需要链接为一个可执行文件。我们需要指定链接地址(运行地址),以确保程序在目标硬件上正确运行。以I.MX6U为例,其链接地址通常设为DDR中的0X87800000
。命令如下:
arm-linux-gnueabihf-ld -Ttext 0X87800000 led.o -o led.elf
-Ttext 0X87800000
:指定链接地址为0X87800000
。-o led.elf
:输出文件名为led.elf
。
存储地址 vs 运行地址
- 存储地址:文件存储的位置(如SD卡、NAND等),可以随意选择。
- 运行地址:代码运行时的地址,由链接时确定,必须与硬件要求一致。例如,I.MX6U的Boot ROM会将代码从SD卡拷贝到
0X87800000
运行。
执行后,生成led.elf
文件。
3. 使用arm-linux-gnueabihf-objcopy
转换格式
led.elf
文件还需转换为.bin
文件以便烧写到SD卡。命令如下:
arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin
-O binary
:输出为二进制格式。-S
:不复制重定位和符号信息。-g
:不复制调试信息。
执行后,生成led.bin
文件。
4. 使用arm-linux-gnueabihf-objdump
反汇编
为了调试或分析代码,可以将led.elf
反汇编为汇编代码:
arm-linux-gnueabihf-objdump -D led.elf > led.dis
-D
:反汇编所有段。> led.dis
:将结果输出到led.dis
文件。
执行后,生成led.dis
文件,包含汇编代码。
三、创建Makefile简化流程
为了方便重复编译,我们可以将上述步骤整合到一个Makefile
文件中:
led.bin: led.s
arm-linux-gnueabihf-gcc -g -c led.s -o led.o
arm-linux-gnueabihf-ld -Ttext 0X87800000 led.o -o led.elf
arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin
arm-linux-gnueabihf-objdump -D led.elf > led.dis
clean:
rm -rf *.o led.bin led.elf led.dis
- 输入
make
执行编译。 - 输入
make clean
清理生成的文件。
四、代码烧写到SD卡
编译完成后,我们需要将led.bin
烧写到SD卡中运行。本教程使用正点原子的imxdownload
工具完成烧写。
1. 准备工作
- 将
imxdownload
拷贝到工程根目录(与led.bin
同级)。 - 赋予执行权限:
chmod +x imxdownload
2. 确定SD卡设备
插入SD卡后,查看设备列表(例如/dev/sdb
、/dev/sdc
等)。可以用以下方法确认:
- 未插入SD卡时,记录已有设备。
- 插入SD卡后,新增的设备(如
/dev/sdd
和分区/dev/sdd1
)即为SD卡。 ls /dev/sd*
/dev/sda /dev/sda1 /dev/sda2 /dev/sdb /dev/sdb1
3. 烧写bin文件
执行烧写命令:
./imxdownload led.bin /dev/sdd
我的:
./imxdownload <.bin file> /dev/sdb
- 烧写速度正常应在几百KB/s以下,若达到几十MB/s则可能失败。
- 烧写完成后,生成
load.imx
文件(在led.bin
前添加了数据头),最终烧写到SD卡的是load.imx
。
注意事项
- 使用新SD卡,确保无重要数据(烧写可能格式化)。
- 若未检测到SD卡,可尝试重启Ubuntu。
五、总结
通过上述步骤,我们完成了从源代码到可执行文件的编译,并成功将其烧写到SD卡。完整的流程包括编译、链接、格式转换、反汇编和烧写,每一步都至关重要。借助Makefile
和imxdownload
,开发过程更加高效。希望本文能帮助你顺利完成ARM开发板的裸机程序部署!