在 Linux 上编译一个 c++ 应用程序,并在 TI TIVA TM4C123GH6PM上刷新它
Compiling an c++ application on Linux and flash it on the TI TIVA TM4C123GH6PM
我正在使用Makefile在Linux中编译一个应用程序。我的编译器来自Imperas(ovp世界)。编译应用程序后,我得到一个 *.elf 文件,我想使用 TI 的 Uniflash 软件在 TI TIVA TM4C123GH6PM上刷新该文件。 当我尝试验证图像时,我总是收到此错误:" [错误] CORTEX_M4_0:文件加载程序:验证失败:地址 0x00008000 处的值不匹配,请验证目标内存和内存映射。
我的生成文件如下所示:
//
IMPERAS_HOME := $(shell getpath.exe "$(IMPERAS_HOME)") include $(IMPERAS_HOME)/bin/Makefile.include
IFNDEF IMPERAS_HOME IMPERAS_ERROR := $(错误"未定义IMPERAS_HOME") 恩迪夫
交叉=ARM_CORTEX_M4F
-include $(IMPERAS_HOME)/lib/$(IMPERAS_ARCH)/CrossCompiler/$(CROSS).makefile.include ifeq ($(CROSS)_CXX),) IMPERAS_ERROR := $(错误"请安装工具链以支持 $(CROSS) ") 恩迪夫
优化=-O
SRC = $(排序 $(通配符主.cpp)) $(排序 $(通配符配置/配置.cpp)) $(排序 $(通配符 Segway/Simulation.cpp)) $(排序 $(通配符 Segway/Segway.cpp)) $(排序 $(通配符传感器/ADC.cpp)) $(排序 $(通配符传感器/ADCSensor.cpp)) $(排序 $(通配符 Antrieb/Motor.cpp)) $(排序 $(通配符传感器/GPIOSensor.cpp)) $(排序 $(通配符计时器/计时器.cpp)) $(排序 $(通配符 Antrieb/PWM.cpp))
EXE = 应用程序。ARM_CORTEX_M4F.精灵
全部: $(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 "# Linked $@" $(V) $(IMPERAS_LINKXX) -o $@ $^ $(IMPERAS_LDFLAGS)
%.o: %.cpp $(V) echo "# 编译 $<" $(V) $(IMPERAS_CXX) -g -c -o $@ $<$(优化) -lm
干净: -rm -f *.elf *.o
真正的清洁:干净 -rm -f *.log
//
如何将内存映射包含在我的生成文件中?内存映射在 *.cmd 文件中定义。这是该文件的链接:https://github.com/LuisAfonso95/TM4C123-Launchpad-Examples/blob/master/srf04/tm4c123gh6pm.cmd
有没有人能解决我的问题并可以帮助我?
如果您需要任何进一步的信息,请告诉我。
谢谢!
Johannes
makefile
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
闪存
MEMORY
{
rom : ORIGIN = 0x00000000, LENGTH = 0x1000
ram : ORIGIN = 0x20000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > rom
.rodata : { *(.rodata*) } > rom
.bss : { *(.bss*) } > ram
}
闪光灯
.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
所以.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工具可以工作,你不需要任何GUIS,否则如果你有一个SWD解决方案(一个st核或发现板,或者你正在运行一个ti launchpad,或者一个jlink或ftdi分线板与正确的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 即可为您提供第一级帮助,然后它们会显示您可以获得帮助并深入研究的其他内容(例如将参数传递给链接器或汇编器)。
- 仅使用绝对值对数组进行排序,并在C++中显示实际值
- 如何创建一个空的全局类并在启动时实例化它
- 在两个类中共享相同的函数调用,并在不需要时避免空实例化
- 在函数内部的声明中初始化数组,并在外部使用它
- C++-我可以创建另一个类的成员并在构造函数中使用它吗
- 缓存std::数组的选定元素,并在c++中自动保持其一致性
- 定义C++新的环境变量并在 bat 文件中使用它
- Visual Studio 2017 停止工作,并在打开后显示许多控制台窗口
- 如何读取单个字符并在输入两个字符序列时输出? 使用 while 循环和C++
- 在 c++ 中模拟输入并在 JAVA 中读取它?
- 是否有必要获取锁并在不需要唤醒线程时通知condition_variable?
- 将通用对象传递给 Rust 并在使用后传递回 C++ 进行销毁
- 动态获取 esp32 的 mac 地址并在以太网库中使用它.
- 从.txt文件中读取浮点型数字并在公式中使用它们
- 如何将成员函数作为参数传递并在派生对象上执行方法列表
- 在C++的头文件中使用常量并在程序中询问其地址的任何潜在危险
- C++ 和 Boost.Python - 如何将变量公开给 python 并在循环中更新它?
- 如何在组合框中列出所有可用的 VCL 样式,并在组合框更改事件中应用该样式C++生成器?
- 是否可以在文本文件中找到最长单词的长度,并在同一个文本文件中读取,只需 1 个 while 循环?
- 在 Linux 上编译一个 c++ 应用程序,并在 TI TIVA TM4C123GH6PM上刷新它