在 Linux 上编译 c++ 应用程序并在 TI TIVA TM4C123GH6PM 上烧写它

Posted

技术标签:

【中文标题】在 Linux 上编译 c++ 应用程序并在 TI TIVA TM4C123GH6PM 上烧写它【英文标题】:Compiling an c++ application on Linux and flash it on the TI TIVA TM4C123GH6PM 【发布时间】:2017-05-18 09:52:32 【问题描述】:

我正在使用 Makefile 在 Linux 中编译一个应用程序。我的编译器来自 Imperas (ovp world)。编译应用程序后,我得到一个 *.elf 文件,我想使用 TI 的 Uniflash 软件在 TI TIVA TM4C123GH6PM 上闪存该文件。 当我尝试验证图像时,我总是收到此错误:“ [错误] CORTEX_M4_0:文件加载器:验证失败:地址 0x00008000 的值不匹配请验证目标内存和内存映射。”

我的 Makefile 看起来像这样:

/////////////////////////////////////// ///////////////////////////////////////// ///////////////////////////////////////// /////////////////

IMPERAS_HOME := $(shell getpath.exe "$(IMPERAS_HOME)") 包括 $(IMPERAS_HOME)/bin/Makefile.include

ifndef IMPERAS_HOME IMPERAS_ERROR := $(错误 "IMPERAS_HOME 未定义") 结束

CROSS=ARM_CORTEX_M4F

-include $(IMPERAS_HOME)/lib/$(IMPERAS_ARCH)/CrossCompiler/$(CROSS).makefile.include ifeq ($($(CROSS)_CXX),) IMPERAS_ERROR := $(error "请安装工具链以支持 $(CROSS)") 结束

优化=-Os

SRC = $(sort $(wildcard main.cpp)) $(sort $(wildcard Configuration/Configuration.cpp)) $(sort $(wildcard Segway/Simulation.cpp)) $(sort $(wildcard Segway/ Segway.cpp)) $(sort $(wildcard Sensor/ADC.cpp)) $(sort $(wildcard Sensor/ADCSensor.cpp)) $(sort $(wildcard Antrieb/Motor.cpp)) $(sort $(wildcard Sensor/GPiosensor.cpp)) $(sort $(wildcard Timer/Timer.cpp)) $(sort $(wildcard Antrieb/PWM.cpp))

EXE = application.ARM_CORTEX_M4F.elf

全部:$(EXE)

%.elf: main.o Segway/Segway.o Timer/Timer.o Sensor/ADC.o Sensor/ADCSensor.o Sensor/GPIOSensor.o Configuration/Configuration.o Antrieb/Motor.o Antrieb/PWM.o $(V) echo "# 链接 $@" $(V) $(IMPERAS_LINKXX) -o $@ $^ $(IMPERAS_LDFLAGS)

%.o: %.cpp $(V) echo "# 编译 $

干净: -rm -f *.elf *.o

realclean: 干净的 -rm -f *.log

/////////////////////////////////////// ///////////////////////////////////////// ///////////////////////////////////////// /////////////////

如何将内存映射包含到我的 Makefile 中?内存映射在 *.cmd 文件中定义。这是文件的链接:https://github.com/LuisAfonso95/TM4C123-Launchpad-Examples/blob/master/srf04/tm4c123gh6pm.cmd

有没有人可以解决我的问题并可以帮助我?

如果您需要更多信息,请告诉我。

谢谢!

约翰内斯

【问题讨论】:

请阅读formatting help然后edit你的问题。 【参考方案1】:

生成文件

ARMGNU = arm-none-eabi

AOPS = --warn --fatal-warnings -mcpu=cortex-m4
COPS = -Wall -Werror -O2 -nostdlib -nostartfiles -ffreestanding  -mcpu=cortex-m4

all : so.bin

clean:
    rm -f *.bin
    rm -f *.o
    rm -f *.elf
    rm -f *.list

flash.o : flash.s
    $(ARMGNU)-as $(AOPS) flash.s -o flash.o

so.o : so.c
    $(ARMGNU)-gcc $(COPS) -mthumb -c so.c -o so.o

so.bin : flash.ld flash.o so.o
    $(ARMGNU)-ld -o so.elf -T flash.ld flash.o so.o
    $(ARMGNU)-objdump -D so.elf > so.list
    $(ARMGNU)-objcopy so.elf so.bin -O binary

flash.ld

MEMORY

    rom : ORIGIN = 0x00000000, LENGTH = 0x1000
    ram : ORIGIN = 0x20000000, LENGTH = 0x1000


SECTIONS

    .text :  *(.text*)  > rom
    .rodata :  *(.rodata*)  > rom
    .bss :  *(.bss*)  > ram

flash.s

.thumb

.thumb_func
.global _start
_start:
stacktop: .word 0x20001000
.word reset
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang

.thumb_func
reset:
    bl notmain
    b hang

.thumb_func
hang:   b .

.thumb_func
.globl PUT32
PUT32:
    str r1,[r0]
    bx lr

so.c

extern void PUT32 ( unsigned int, unsigned int );

int notmain ( void )

    PUT32(0x20000400,0x12345678);
    return(0);

制作

arm-none-eabi-as --warn --fatal-warnings -mcpu=cortex-m4 flash.s -o flash.o
arm-none-eabi-gcc -Wall -Werror -O2 -nostdlib -nostartfiles -ffreestanding  -mcpu=cortex-m4 -mthumb -c so.c -o so.o
arm-none-eabi-ld -o so.elf -T flash.ld flash.o so.o
arm-none-eabi-objdump -D so.elf > so.list
arm-none-eabi-objcopy so.elf so.bin -O binary

检查反汇编以查看向量表是否位于正确的位置并正确构建,可以将一个全局变量放入其中并保存一个值(运行时),以查看它是否位于正确的位置。

Disassembly of section .text:

00000000 <_start>:
   0:   20001000    andcs   r1, r0, r0
   4:   00000041    andeq   r0, r0, r1, asr #32
   8:   00000047    andeq   r0, r0, r7, asr #32
   c:   00000047    andeq   r0, r0, r7, asr #32
  10:   00000047    andeq   r0, r0, r7, asr #32
  14:   00000047    andeq   r0, r0, r7, asr #32
  18:   00000047    andeq   r0, r0, r7, asr #32
  1c:   00000047    andeq   r0, r0, r7, asr #32
  20:   00000047    andeq   r0, r0, r7, asr #32
  24:   00000047    andeq   r0, r0, r7, asr #32
  28:   00000047    andeq   r0, r0, r7, asr #32
  2c:   00000047    andeq   r0, r0, r7, asr #32
  30:   00000047    andeq   r0, r0, r7, asr #32
  34:   00000047    andeq   r0, r0, r7, asr #32
  38:   00000047    andeq   r0, r0, r7, asr #32
  3c:   00000047    andeq   r0, r0, r7, asr #32

00000040 <reset>:
  40:   f000 f804   bl  4c <notmain>
  44:   e7ff        b.n 46 <hang>

00000046 <hang>:
  46:   e7fe        b.n 46 <hang>

00000048 <PUT32>:
  48:   6001        str r1, [r0, #0]
  4a:   4770        bx  lr

0000004c <notmain>:
  4c:   b508        push    r3, lr
  4e:   4903        ldr r1, [pc, #12]   ; (5c <notmain+0x10>)
  50:   4803        ldr r0, [pc, #12]   ; (60 <notmain+0x14>)
  52:   f7ff fff9   bl  48 <PUT32>
  56:   2000        movs    r0, #0
  58:   bd08        pop r3, pc
  5a:   bf00        nop
  5c:   12345678    eorsne  r5, r4, #120, 12    ; 0x7800000
  60:   20000400    andcs   r0, r0, r0, lsl #8

在正确的地方看向量表,lsbit设置向量表地址等

这是一个非常通用的 cortex-m 程序,几乎可以在所有内核上运行,有些你可能必须将堆栈指针 init 减少到 0x20000800 或更小,同样在命令行上指定 cortex-m0 而不是 m4 以使其更通用,在这种情况下它没有生成任何 armv7-m thumb2 扩展。

查看您的工具对生成的这个 so.elf 文件的说明,它确实比这更简单(删除 bl notmain)并且只将 flash.s 链接到一个 elf,但没有比这简单得多。如果它不起作用,那么问题可能是其他问题,该工具可能正在寻找某些东西。如果这真的是一个 tiva c 部分,那么 lm4flash 工具可能会工作并且您不需要任何 gui,否则如果您有 SWD 解决方案(st nucleo 或发现板,或者您在 ti 启动板上运行,或者带有正确 ftdi 部分的 jlink 或 ftdi 接线板(支持 mpsse 且电压适合您的目标的电平)。如果它不起作用,那么该工具可能正在寻找 elf 文件中通常不需要的特殊内容. 我假设在问这里之前你查过那个错误信息?

如果它确实加载并显示运行,并且如果您有调试器,您可以停止 cpu 并读取 0x20000400,并且应该看到程序写入的 0x12345678 作为程序确实加载和运行的进一步确认。然后检查我的 makefile、链接器脚本以及它在编译过程中的使用位置,而不是你的。

如果您尝试使用 gcc 调用所有工具链,那么您需要了解其他一些事情,例如

arm-whatever-gcc other flags, -Xlinker '-T flash.ld' flash.s so.c -o so.elf

基本上一两个 -Xlinker 或任何正确的命令行选项我认为我为每个 ld 选项使用一个 -Xlinker(-Xlinker -T -Xlinker flash.ld,但是 YMMV,我几乎从来没有 gcc 这样做额外的工作,如果我可以避免它更喜欢直接调用它们,我让 gcc 调用汇编器以使编译的输出成为一个对象,但除此之外......)。仅在不带选项的情况下运行 gcc 即可为您提供第一级帮助,然后它们会显示您可以获得帮助和深入研究的其他内容(例如将参数传递给链接器或汇编器)。

【讨论】:

以上是关于在 Linux 上编译 c++ 应用程序并在 TI TIVA TM4C123GH6PM 上烧写它的主要内容,如果未能解决你的问题,请参考以下文章

在 Linux 服务器上编译 C++ 程序时 Intel 编译器的语法

VRPN C++ 代码可在 Linux 上编译,但不能在 Windows 上编译

在 Windows 和 Linux 上编译 C++:ifdef 开关 [重复]

BFD_RELOC_64:使用 C++ 在 32 位 linux 上编译汇编器指令

将 Visual Studio C++ 项目“移植”到 Linux 上编译的最简单方法是啥?

在 Windows 上编译+分发 Linux 代码