提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
一、交叉编译器的安装
1复制交叉编译器软件到Ubuntu系统中
在Ubuntu系统中新建个tool目录用来存放交叉编译器。
2解压交叉编译器
sudo tar -vxf gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf.tar.xz
等待解压完成,解压完成以后会生成一个名为“gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf”的文件夹,这个文件夹里面就是我们的交叉编译工具链。
3修改环境变量
修改/etc/profile 文件,在profile中添加编译器bin的目录,输入指令如下
pwd
sudo vi /etc/profile
在文档最后添加如下目录
4安装交叉编译器所需要的C库
输入指令如下
sudo apt-get install lsb-core lib32stdc++6
5重启系统,验证交叉编译器
输入指令如下,查看交叉编译器版本
arm-linux-gnueabihf-gcc -v
二、代码的编译过程
1编译指令
代码如下:
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
💦第一条指令
💦源文件都会通过编译器被编译成对于的.o文件,在STM32中也一样的,MDK编译后也会生成对于的.o文件如下图所示,一个工程中所有的 C文件和汇编文件都会编译生成一个对应的.o 文件,我们需要将这.o 文件链接起来组合成可执行文件
💦STM32编译过程对应的.o文件。
💦第二条指令
💦arm-linux-gnueabihf-ld 用来将众多的.o 文件链接到一个指定的链接位置。在SMT32 中没有“链接”的这个概念,我们一般用 MDK 编写好代码,然后点击“编译”,MDK 就会自动帮我们编译好整个工程,最后再点击“下载”就可以将代码下载到开发板中。这是因为链接这个操作 MDK 或者 IAR 已经帮你做好了,下面这个图左侧的IROM1 是设置 STM32 芯片的 ROM 起始地址和大小的,右边的 IRAM1 是设置 STM32 芯片的 RAM 起始地址和大小的。其中 0X08000000 就是 STM32 内部 ROM 的起始地址,编译出来的指令肯定是要从 0X08000000 这个地址开始存放的。
💦对于STM32 来说 0X08000000 就是它的链接地址,这些.o 文件就是这个链接地址开始依次存放,最终生成一个可以下载的 hex 或者 bin 文件,我们可以打开.map 文件查看一下这些文件的链接地址
💦从可以看出 STM32 的各个.o 文件所处的位置,起始位置是 0X08000000。由此可以得知,我们用 MDK 开发 STM32 的时候也是有链接的,只是这些工作 MDK 都帮我们全部做好了。
💦因此在Linux中,我们在烧录程序前要确认可执行文件的运行起始地址,也就是链接地址。这里我们要区分“存储地址”和“运行地址”这两个概念,存储地址就是可执行文件存储在哪里,可执行文件的存储地址可以随意选择。运行地址就是代码运行的时候所处的地址,这个我们在链接的时候就已经确定好了,代码要运行,那就必须处于运行地址处,否则代码肯定运行出错。比如 I.MX6U 支持 SD 卡、EMMC、NAND 启动,因此代码可以存储到 SD 卡、EMMC 或者 NAND 中,但是要运行的话就必须将代码从 SD 卡、EMMC 或者NAND 中复制到运行地址(链接地址)处,“存储地址”和“运行地址”可以一样,比如STM32 的存储起始地址和运行起始地址都是 0X08000000。
💦对于I.MX6U的程序,可以烧录到 SD 卡中,上电以后 I.MX6U 的内部 boot rom 程序会将可执行文件拷贝到链接地址处,这个链接地址可以在 I.MX6U 的内部 128KB RAM 中(0X900000~0X91FFFF),也可以在外部的 DDR 中。在 DDR中,链接起始地址为 0X87800000。I.MX6U-ALPHA 开发板的 DDR 容量有两种:512MB 和256MB,起始地址都为 0X80000000,只不过 512MB 的终止地址为 0X9FFFFFFF,而 256MB 容量的终止地址为 0X8FFFFFFF。之所以选择 0X87800000 这个地址是因为 Uboot 其链接地址就是 0X87800000,这样方便统一使用 0X87800000 这个链接地址。确定了链接地址以后就可以使用 arm-linux-gnueabihf-ld 来将前面编译出来的 led.o 文件接到 0X87800000 这个地址,使用如下命令生成.elf文件
arm-linux-gnueabihf-ld -Ttext 0X87800000 led.o -o led.elf
💦DDR起始地址:DDR通过MMDC控制,MMDC在内存中的映射地址如下图所示,与STM32的静态存储访问器FSMC一样原理,DDR大小由DDR芯片决定。
💦第三条指令
💦led.elf 文件也不是我们最终烧写到 SD 卡中的可执行文件,我们要烧写的.bin 文件,因此还需要将 led.elf 文件转换为.bin 文件,这里我们就需要用到 arm-linux-gnueabihf-objcopy 这个工具。
arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin
💦上述命令中,“-O”选项指定以什么格式输出,后面的“binary”表示以二进制格式输出,选项“-S”表示不要复制源文件中的重定位信息和符号信息,“-g”表示不复制源文件中的调试
信息。上述命令执行完成以后,生成.bin文件。
💦第四条指令
💦大多数情况下我们都是用 C 语言写程序,有时候需要查看其汇编代码来调试代码,因此就需要进行反汇编,一般可以将 elf 文件反汇编,比如如下命令
arm-linux-gnueabihf-objdump -D led.elf > led.dis
上述代码中的“-D”选项表示反汇编所有的段,反汇编完成以后就会在当前目录下出现一个名为 led.dis 文件。打开.dis文件内容就包括链接地址。