我正试图使用arm-none eabi gcc为TM4C123GXL微控制器编译一个简单的项目。在main
内部,我调用memcpy
只是为了测试它是否按预期工作,但它会导致故障。导致故障的原因是在memcpy
的反汇编过程中,第一条指令之一是b.n 0xc7a
,它将CPU带到一些未使用的闪存段。就好像memcpy
期望其他函数在那个位置,但我不明白为什么当任何依赖项也应该链接时会发生这种情况。事实上,他们确实如此。看看ELF中的符号,就会发现其他功能也包括在内。它编译时没有任何警告或错误。
这是我正在使用的Makefile:
PROJECT = main
SRCS = $(wildcard src/*.c)
OBJ = obj/
OBJS = $(addprefix $(OBJ), $(notdir $(SRCS:.c=.o)))
INC = inc/
LD_SCRIPT = TM4C123GH6PM.ld
CC = arm-none-eabi-gcc
LD = arm-none-eabi-ld
OBJCOPY = arm-none-eabi-objcopy
RM = rm -rf
MKDIR = @mkdir -p $(@D)
# EDIT: include -O0 flag
OPT += -O0
CFLAGS = -ggdb3 -mthumb -mcpu=cortex-m4 -mfpu=fpv4-sp-d16
CFLAGS += -mfloat-abi=softfp -MD -std=c99 -c -Wextra -Wall -Wno-missing-braces
CFLAGS += $(OPT)
all: bin/$(PROJECT).elf
$(OBJ)%.o: src/%.c
$(MKDIR)
$(CC) -o $@ $^ -I$(INC) $(CFLAGS)
bin/$(PROJECT).elf: $(OBJS)
$(MKDIR)
$(CC) -o $@ $^ -Wl,-T $(LD_SCRIPT) -Wl,-e Reset_Handler
$(OBJCOPY) -O binary $@ bin/$(PROJECT).bin
clean:
-$(RM) obj
-$(RM) bin
和我的main
:
#include <stdint.h>
#include <string.h>
int main(void){
uint8_t x[] = {1,2,3};
uint8_t y[] = {0,0,0};
uint8_t *xptr = x;
uint8_t *yptr = y;
memcpy(yptr, xptr, 3);
while (1)
;
}
还有我的Reset_Handler
,作为衡量标准:
void Reset_Handler(void)
{
int *src, *dest;
/* copying of the .data values into RAM */
src = &_etext;
for (dest = &_data; dest < &_edata;)
{
*dest++ = *src++;
}
/* initializing .bss values to zero*/
for (dest = &__bss_start__; dest < &__bss_end__;)
{
*dest++ = 0;
}
main();
}
为了使用Newlib的标准C库,我还需要做其他事情吗?
KamilCuk的评论帮助我解决了这个问题,特别是在链接时包括-mthumb
。
我认为之所以需要这样做,是因为当没有指定任何选项来arm none-eabi-gcc时(就像Makefile在第二步调用它进行链接时的情况一样(,它默认使用-marm
:
COLLECT_GCC_OPTIONS='-o' 'bin/main.elf' '-v' '-mcpu=arm7tdmi' '-mfloat-abi=soft'
'-marm' '-mlibarch=armv4t' '-march=armv4t' '-dumpdir' 'bin/main.elf.'
TM4C使用仅支持Thumb指令的Cortex-M4F CPU。我自己的文件被编译为Thumb指令,因为我在链接之前将-mthumb
包含在它们的编译中,但在链接文件时没有指定此选项,因此包含了memcpy
的ARM版本。CPU将ARM指令解释为Thumb指令,这会导致各种错误。
此外,正如Guarav Pathak所指出的,当指定-mcpu=cortex-m4
时,没有必要手动包含-mthumb
,因为该标志会自动包含-mthumb
。只要以某种方式包含-mthumb
,这将指导编译器链接其他编译单元的Thumb版本。