printf in newlib is not working in baremetal ARM environment

2

I am working in a bare-metal ARM project in which I am trying to integrate newlib library. As a beginner, I am trying to make the printf function working first so that I can see the standard output through UART. I have already gone through many on-line documents that describes how to get this done. Instead of blindly following the steps, I did everything myself by learning things from those documents. I made many mistakes in the beginning but fixed them one by one and kept the work progressing. But now I have stuck with an issue which no one has ever seems to be experienced so far, according to my internet search. Now let me come to the actual, issue.

The printf function is returning without calling my implementation of _write function. When I debug I can see that the printf is invoking other system calls that I have written myself(Like _isatty, _sbrk and _fstat).

These are the system calls that I have implemented in order to resolve the linking issues(undefined references)

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;
}

My linker script

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
}

My 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

Please let me know if any further information is needed from my side. Thank you in advance

EDIT:

Start-up code

/* 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
c
gcc
arm
bare-metal
newlib
asked on Stack Overflow Jul 5, 2017 by Sreeyesh • edited Jul 5, 2017 by dbush

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0