我正在一个裸机ARM项目中工作,我正在尝试集成newlib库。作为初学者,我试图让printf
函数先工作,以便通过UART看到标准输出。我已经阅读了很多描述如何完成这项工作的在线文档。我没有盲目地遵循这些步骤,而是通过从这些文档中学习东西来完成所有工作。我在开始时犯了很多错误,但是一个接一个地修复它们并保持工作进展。
但根据我的互联网搜索,现在我已经遇到了一个迄今为止似乎没有人经历过的问题。现在让我谈谈实际问题。
printf
函数返回时没有调用_write
函数的实现。当我调试时,我可以看到printf
正在调用我自己编写的其他系统调用(例如_isatty
,_sbrk
和_fstat
)。
这些是我为解决链接问题而实现的系统调用(未定义的引用)
extern char __heap_start__;
extern char __heap_end__;
void _exit(int status)
{
while (1);
}
void *_sbrk(int incr)
{
static char *heap_end = &__heap_start__;
char *base = heap_end;
if(heap_end + incr > &__heap_end__)
{
errno = ENOMEM;
return (void *)-1;
}
heap_end += incr;
return base;
}
int _write(int fd, char *buff, int size)
{
int i;
for(i = 0; i < size; i++)
{
UART0_write_char(buff[i]);
}
return i;
}
int _read(int fd, char *buff, int size)
{
return 0;
}
int _open(const char *name, int flags,int mode)
{
return 0;
}
void _close(int fd)
{
}
int _isatty(int fd)
{
return 1;
}
int _fstat(int fd, struct stat *st)
{
st->st_mode = S_IFCHR;
return 0;
}
off_t _lseek(int fd, off_t offset, int whence)
{
return 0;
}
我的链接描述文件
STACK_HEAP_BOUNDARY_OFFSET = 0;
MEMORY
{
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 512K
SRAM (rw) : ORIGIN = 0x40000000, LENGTH = 32K
}
SECTIONS
{
.text :
{
startup.o (.text)
*(.text .txt.*)
*(.glue_7)
*(.glue_7t)
. = ALIGN(4);
} > FLASH
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > FLASH
.ARM :
{
*(.ARM.exidx*)
} >FLASH
.rodata :
{
*(.rodata .rodata.*)
. = ALIGN(4);
} > FLASH
.data :
{
__data_load__ = LOADADDR (.data);
__data_start__ = .;
*(.data .data.*)
. = ALIGN(4);
__data_end__ = .;
} > SRAM AT > FLASH
.bss :
{
__bss_start__ = .;
*(.bss .bss.*)
*(COMMON)
. = ALIGN(4);
__bss_end__ = .;
} > SRAM
.heap :
{
__heap_start__ = .;
PROVIDE(end = __heap_start__);
PROVIDE(_heap_start = __heap_start__);
. = . + ((LENGTH(SRAM) - (. - (ORIGIN(SRAM)))) / 2);
. += STACK_HEAP_BOUNDARY_OFFSET;
. = ALIGN(4);
__heap_end__ = .;
PROVIDE(_heap_end = __heap_end__);
} > SRAM
.stack :
{
__stack_start__ = .;
. = . + (LENGTH(SRAM) - (. - (ORIGIN(SRAM))));
. = ALIGN(4);
__stack_end__ = .;
__stack_size__ = __stack_end__ - __stack_start__;
__IRQ_stack_top__ = (__stack_start__ + (__stack_size__ / 2));
} > SRAM
}
我的Makefile
TOOLCHAIN_PREFIX:=arm-none-eabi-
CC := $(TOOLCHAIN_PREFIX)gcc
LD := $(TOOLCHAIN_PREFIX)ld
AS := $(TOOLCHAIN_PREFIX)as
AR := $(TOOLCHAIN_PREFIX)ar -cr
OBJCOPY := $(TOOLCHAIN_PREFIX)objcopy
RM := rm -f
TARGET := image.hex
OBJS := startup.o $(patsubst %.c,%.o,$(wildcard *.c))
CFLAGS := -mcpu=arm7tdmi-s -g3 -Wall -I. -gdwarf-2
AS_FLAGS := -mcpu=arm7tdmi-s -g3 -gdwarf-2
LD_FLAGS := -Wl,-Map,$(TARGET:%.hex=%).map -nostartfiles
LD_SCRIPT := lpc2138.ld
all : $(TARGET)
$(TARGET) : $(TARGET:%.hex=%.elf)
$(OBJCOPY) -O ihex $< $@
$(TARGET:%.hex=%.elf) : $(OBJS)
$(CC) -o $@ -T $(LD_SCRIPT) $(OBJS) $(LD_FLAGS)
startup.o : startup.s
$(AS) $(AS_FLAGS) -o $@ $<
%.o : %.c
$(CC) -c $(CFLAGS) -o $@ $<
clean :
$(RM) $(TARGET) $(TARGET:%.hex=%.elf) $(TARGET:%.hex=%).map *.o
如果我方需要进一步的信息,请告诉我。提前谢谢
编辑:
启动代码
/* Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs */
Mode_USR = 0x10
Mode_FIQ = 0x11
Mode_IRQ = 0x12
Mode_SVC = 0x13
Mode_ABT = 0x17
Mode_UND = 0x1B
Mode_SYS = 0x1F
I_Bit = 0x80 /* when I bit is set, IRQ is disabled */
F_Bit = 0x40 /* when F bit is set, FIQ is disabled */
.text
.arm
.global _start
.func _start
_start:
B _reset /* Reset vector */
B _loop /* Undefined Instruction */
B _loop /* Software Interrupt */
B _loop /* Prefetch Abort */
B _loop /* Data Abort */
NOP /* Reserved */
LDR pc, [pc, #-0x0FF0] /* VicVectAddr */
/* LDR pc, _fiq_addr */
B _loop /* FIQ Handler */
_reset:
/* Enable FIQ and IRQ */
MSR CPSR_c,#(Mode_IRQ | I_Bit | F_Bit)
LDR SP, =__IRQ_stack_top__
MSR CPSR_c,#Mode_SVC
/* Relocate the .data section (copy from ROM to RAM) */
LDR r0,=__data_load__
LDR r1,=__data_start__
LDR r2,=__data_end__
_l1:
CMP r1,r2
LDMLTIA r0!,{r3}
STMLTIA r1!,{r3}
BLT _l1
/* Clear the .bss section (zero init) */
LDR r1,=__bss_start__
LDR r2,=__bss_end__
MOV r3,#0
_l2:
CMP r1,r2
STMLTIA r1!,{r3}
BLT _l2
LDR sp,=__stack_end__
LDR FP,=__stack_end__
LDR r0,=main
MOV lr,pc
BX r0
_loop:
B _loop
/* _fiq_addr:
.word VIC_FIQ_handler
*/
.endfunc
.end