cancel
Showing results for 
Search instead for 
Did you mean: 

Trouble getting printf working on STM32F412 - printf not getting linked.

ABuja.1
Associate II

I included a syscalls.c file where I have my _write function, but it never gets called. I've been working off of the UART_printf application in the Cube examples, but I'm really having trouble finding what's missing and it's starting to drive me crazy.

I have a feeling it's something to do with my compiler, because printf is not in the generated map file at all. I've even tried a different arm gcc compiler.

Here is my Makefile:

TARGET = FALCON
DEBUG = 1
OPT =
BUILD_DIR = _build
 
 
FALCON_ROOT = ../../../..
DEV_ROOT = $(FALCON_ROOT)/development
LIB_ROOT = $(DEV_ROOT)/libraries
PROJ_DIR = ..
FLN_BSP_DIR = $(DEV_ROOT)/system/boards/stm_dev_bsp
SDK_ROOT = $(FALCON_ROOT)/dependencies/stm/STM32F4_Cube
FREERTOS_ROOT = $(FALCON_ROOT)/dependencies/freertos/FreeRTOSv10.4.1/FreeRTOS/Source
FREERTOS_PORTABLE = $(FREERTOS_ROOT)/portable/GCC/ARM_CM4F
HAL_DIR = $(SDK_ROOT)/Drivers/STM32F4xx_HAL_Driver
BSP_DIR = $(SDK_ROOT)/Drivers/BSP/STM32412G-Discovery
CMSIS_DIR = $(SDK_ROOT)/Drivers/CMSIS
 
######################################
# source
######################################
# C sources
C_SOURCES += \
$(HAL_DIR)/Src/stm32f4xx_hal.c \
$(HAL_DIR)/Src/stm32f4xx_hal_cortex.c \
$(HAL_DIR)/Src/stm32f4xx_hal_gpio.c \
$(HAL_DIR)/Src/stm32f4xx_hal_rcc.c \
$(HAL_DIR)/Src/stm32f4xx_hal_tim.c \
$(HAL_DIR)/Src/stm32f4xx_hal_tim_ex.c \
$(HAL_DIR)/Src/stm32f4xx_hal_uart.c \
$(BSP_DIR)/stm32412g_discovery.c \
$(FLN_BSP_DIR)/bsp.c \
$(FREERTOS_ROOT)/tasks.c \
$(FREERTOS_ROOT)/queue.c \
$(FREERTOS_ROOT)/list.c \
$(FREERTOS_ROOT)/timers.c \
$(FREERTOS_ROOT)/event_groups.c \
$(FREERTOS_ROOT)/stream_buffer.c \
$(FREERTOS_ROOT)/portable/MemMang/heap_4.c \
$(FREERTOS_PORTABLE)/port.c \
$(PROJ_DIR)/src/main.c \
$(PROJ_DIR)/src/stm32f4xx_it.c \
$(PROJ_DIR)/src/system_stm32f4xx.c \
$(PROJ_DIR)/src/syscalls.c \
$(PROJ_DIR)/src/leds.c \
$(PROJ_DIR)/src/logger.c \
 
# ASM sources
ASM_SOURCES = startup_stm32f412zx.s
 
# C includes
C_INCLUDES += \
			-I$(HAL_DIR)/Inc \
			-I$(BSP_DIR)/ \
			-I$(FLN_BSP_DIR)/ \
			-I$(PROJ_DIR)/include \
			-I$(CMSIS_DIR)/Device/ST/STM32F4xx/Include \
			-I$(CMSIS_DIR)/Include \
 			-I$(FREERTOS_ROOT)/include \
 			-I$(FREERTOS_PORTABLE)
 
# C defines
C_DEFS =  \
-DUSE_HAL_DRIVER \
-DSTM32F412Zx \
-DUSE_STM32412G_DISCOVERY
 
#######################################
# binaries
#######################################
PREFIX = arm-none-eabi-
 
ifdef GCC_PATH
CC = $(GCC_PATH)/$(PREFIX)gcc
AS = $(GCC_PATH)/$(PREFIX)gcc -x assembler-with-cpp
CP = $(GCC_PATH)/$(PREFIX)objcopy
SZ = $(GCC_PATH)/$(PREFIX)size
else
CC = $(PREFIX)gcc
AS = $(PREFIX)gcc -x assembler-with-cpp
CP = $(PREFIX)objcopy
SZ = $(PREFIX)size
endif
HEX = $(CP) -O ihex
BIN = $(CP) -O binary -S
 
#######################################
# CFLAGS
#######################################
 
ASFLAGS = -mcpu=cortex-m4 -g3 -c -x assembler-with-cpp --specs=nano.specs -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb
 
CFLAGS = -mcpu=cortex-m4 $(C_DEFS) $(C_INCLUDES) -std=gnu11 -g3 -DSTM32F412Zx -DUSE_HAL_DRIVER -DUSE_STM32412G_DISCOVERY  -Os -ffunction-sections -Wall -fstack-usage --specs=nano.specs -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb
 
#######################################
# LDFLAGS
#######################################
# link script
LDSCRIPT = $(PROJ_DIR)/build/stm32_flash.ld
 
# libraries
LDFLAGS = -mcpu=cortex-m4 -T$(LDSCRIPT) --specs=nosys.specs -Wl,-Map=$(BUILD_DIR)/$(TARGET).map -Wl,--gc-sections -static --specs=nano.specs -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb -Wl,--start-group -lc -lm -Wl,--end-group
 
# default action: build all
all: $(BUILD_DIR)/$(TARGET).elf $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).bin
 
 
#######################################
# build the application
#######################################
# list of objects
OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(C_SOURCES:.c=.o)))
vpath %.c $(sort $(dir $(C_SOURCES)))
# list of ASM program objects
OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(ASM_SOURCES:.s=.o)))
vpath %.s $(sort $(dir $(ASM_SOURCES)))
 
$(BUILD_DIR)/%.o: %.c Makefile | $(BUILD_DIR)
	$(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.c=.lst)) $< -o $@
 
$(BUILD_DIR)/%.o: %.s Makefile | $(BUILD_DIR)
	$(AS) -c $(CFLAGS) $< -o $@
 
$(BUILD_DIR)/$(TARGET).elf: $(OBJECTS) Makefile
	$(CC) $(OBJECTS) $(LDFLAGS) -o $@
	$(SZ) $@
 
$(BUILD_DIR)/%.hex: $(BUILD_DIR)/%.elf | $(BUILD_DIR)
	$(HEX) $< $@
 
$(BUILD_DIR)/%.bin: $(BUILD_DIR)/%.elf | $(BUILD_DIR)
	$(BIN) $< $@
 
$(BUILD_DIR):
	mkdir $@
 
#######################################
# clean up
#######################################
clean:
	-rm -fR $(BUILD_DIR)
 
flash:
	st-flash write $(BUILD_DIR)/$(TARGET).bin 0x8000000
	st-flash reset
 
#######################################
# dependencies
#######################################
-include $(wildcard $(BUILD_DIR)/*.d)
 

and here is my syscalls file:

#include <sys/stat.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>
#include <sys/times.h>
 
extern int errno;
extern int __io_putchar(int ch) __attribute__((weak));
extern int __io_getchar(void) __attribute__((weak));
 
register char * stack_ptr asm("sp");
 
char *__env[1] = { 0 };
char **environ = __env;
 
 
void initialise_monitor_handles()
{
}
 
int _getpid(void)
{
	return 1;
}
 
int _kill(int pid, int sig)
{
	errno = EINVAL;
	return -1;
}
 
void _exit (int status)
{
	_kill(status, -1);
	while (1) {}		/* Make sure we hang here */
}
 
int _read (int file, char *ptr, int len)
{
	int DataIdx;
 
	for (DataIdx = 0; DataIdx < len; DataIdx++)
	{
		*ptr++ = __io_getchar();
	}
 
return len;
}
 
int _write(int file, char *ptr, int len)
{
	int DataIdx;
 
	for (DataIdx = 0; DataIdx < len; DataIdx++)
	{
		__io_putchar(*ptr++);
	}
	return len;
}
 
caddr_t _sbrk(int incr)
{
	extern char end asm("end");
	static char *heap_end;
	char *prev_heap_end;
 
	if (heap_end == 0)
		heap_end = &end;
 
	prev_heap_end = heap_end;
	if (heap_end + incr > stack_ptr)
	{
//		write(1, "Heap and stack collision\n", 25);
//		abort();
		errno = ENOMEM;
		return (caddr_t) -1;
	}
 
	heap_end += incr;
 
	return (caddr_t) prev_heap_end;
}
 
int _close(int file)
{
	return -1;
}
 
 
int _fstat(int file, struct stat *st)
{
	st->st_mode = S_IFCHR;
	return 0;
}
 
int _isatty(int file)
{
	return 1;
}
 
int _lseek(int file, int ptr, int dir)
{
	return 0;
}
 
int _open(char *path, int flags, ...)
{
	/* Pretend like we always fail */
	return -1;
}
 
int _wait(int *status)
{
	errno = ECHILD;
	return -1;
}
 
int _unlink(char *name)
{
	errno = ENOENT;
	return -1;
}
 
int _times(struct tms *buf)
{
	return -1;
}
 
int _stat(char *file, struct stat *st)
{
	st->st_mode = S_IFCHR;
	return 0;
}
 
int _link(char *old, char *new)
{
	errno = EMLINK;
	return -1;
}
 
int _fork(void)
{
	errno = EAGAIN;
	return -1;
}
 
int _execve(char *name, char **argv, char **env)
{
	errno = ENOMEM;
	return -1;
}

I would really appreciate whatever help anyone can provide.

3 REPLIES 3
hs2
Senior

Maybe i‘m wrong but isn’t the CFLAG -M (or variants like -MM etc) needed to generate the dependency (.d) files ?

However, so far your Makefile and syscall wrappers seem to be ok. What‘s the problem in more detail ? Linker error ? Application not working as expected ?

Everything links, and my application works as expected other than printf not doing anything and never calling _write. When I add a -M flag I get the following output:

_build/stm32f4xx_hal.o: file not recognized: File truncated
collect2: error: ld returned 1 exit status
make: *** [_build/FALCON.elf] Error 1

hs2
Senior

I've checked my Makefiles and I'm using -MMD to let GCC generate .d files along with (compiled) object files (.o).

-M seems to generate just the dependency file as the specified output (.o) file which is not a linkable object file. Hence the linker error.

And I'm using this to include them (in a bit more generic way):

DEPS := $(OBJECTS:o=d)
-include $(DEPS)

Sorry - no idea regarding your printf problem :(