I'm trying to get started with the RK3568 controller (cortex a55)
I have a project and a makefile
I managed to output the character using registers and flashing the LED.
But if I try to output a string using printf, the program just freezes without any signs of life.
I was looking for a solution to the problem, and the main solution is to implement the _write function(int file, char *ptr, int len), which the standard printf function should use. But it doesn't help.
I tried to connect another Printf function from github and it works. I don't understand what the reason is.
I tried to call other functions from the standard library, for example strlen and it has the same behavior as printf
int _write(int file, char *ptr, int len)
{
__io_putchar('w');
int DataIdx;
for (DataIdx = 0; DataIdx < len; DataIdx++)
{
__io_putchar( *ptr++ );
}
return len;
}
I am using the AArch64 bare-metal target compiler (aarch64-none-elf)
I tried using another AArch32 bare-metal target compiler (arm-none-eabi), but there are even more problems with it. He can't even build the project and throws assembler errors.
Error: selected processor does not support requested special purpose register -- `msr tpidr_el 1,xzr'
Error: ARM register expected -- `ldr x1,=_start'
and many more similar
my makefile, maybe its help
PWD := $(shell pwd)
PRJ_BUILD := $(PWD)/build
CC := aarch64-none-elf-gcc
LD := aarch64-none-elf-ld
OBJCOPY := aarch64-none-elf-objcopy
OBJDUMP := aarch64-none-elf-objdump
SRC := src/entry_point.S
SRC += src/cache.S
SRC += src/main.c
SRC += src/stub.c
SRC := $(addprefix $(PWD)/,$(SRC))
INCLUDES := .
INCLUDES += src
INCLUDES := $(addprefix -I$(PWD)/,$(INCLUDES))
CFLAGS := -c -g
#CFLAGS += -march=armv8.2-a -mcpu=cortex-a55
CFLAGS += -mcpu=cortex-a55
#-mcpu=cortex-a55 -mfloat-abi=hard
define get_library_path
$(shell dirname $(shell $(CC) $(CFLAGS) -print-file-name=$(1)))
endef
LDFLAGS += -L $(call get_library_path,libc.a)
LDFLAGS += -L $(call get_library_path,libgcc.a)
LDFLAGS += -T $(PWD)/link.lds -lgcc -lc
all: app.elf
app.elf:
$(info $(PWD))
$(info SRC:[$(SRC)])
$(info INCLUDES:[$(INCLUDES)])
cd $(PRJ_BUILD) && $(CC) $(CFLAGS) $(INCLUDES) $(SRC)
cd $(PRJ_BUILD) && \
$(LD) -o app.elf $(PRJ_BUILD)/*.o \
$(LDFLAGS) -Map app.map
cd $(PRJ_BUILD) && $(OBJCOPY) -O binary app.elf app.bin
cd $(PRJ_BUILD) && $(OBJDUMP) app.elf -dS > app.lst
clean:
cd $(PRJ_BUILD) && rm -f *.*
I would be glad to at least some advice
In the end I was able to solve this problem
I tried to do the following
I implemented the _sbrk function (get from this)
I tried to highlight heap and stack
I implemented the _write function (but did not touch _write_r [!])
I provided the implementation of the memcmp, memset, memmove, memcpy functions
In reality, item No. has the greatest impact on work.4. If you remove everything except point 4, then the code works and I can output "Hello world"!
Let me remind you that I use aarch64-none-elf-gcc
item 4 I took from here https://embeddedartistry.com/blog/2017/03/22/memset-memcpy-memcmp-and-memmove/
Related
I wanted to create a C program to create several different executable binaries from the same Makefile with different names.
but as everytime I run "make" of a pretty large program, they have this bunch logs output... and if i made several of this the terminal would be so "dirty"
So the question, is it actually okay to run "make" in background, so i don't have to see those log?
is it a good idea? or does this actually has no relation with putting it to the background or so?
and if yes, how can i do so?
For the program it's more or less like below, where tmp2 is array of the binaries name
for (int j = 0; tmp2[j] != NULL; j++)
{
printf("-> %s\n", tmp2[j]);
char command[128] = "";
sprintf(command, "make -C %s TARGET=%s all", "file/path/", tmp2[j]);
system(command);
}
and I tried to look up for running linux command in background like adding & at the end of the command, but it still shows the log
text.c:442:3: warning: blablabla
gcc -W -Wall -Wextra -c -g -Os -I. test1.c
gcc -W -Wall -Wextra -c -g -Os -I. test2.c
gcc -g -o STEM_ECS2_SERVICE_3 main.o json.o config.o debug.o -lnsl -lm -ldl -lc -lmysqlclient -lm
/bin/mv *.o ./object
the log is sth like above, its the simplified version, it's just all the stuff from -Wall and the actual command like gcc stuff
So is there actually any way to not see the "make" log?
EDIT
for the make file
include ../../Make.cf
OBJ_DIR = ./object
CFLAGS = -g -Os $(INCDIR) $(MYSQLINC) -I./include -export-dynamic
LDFLAGS = $(SYSNLIB) $(SYSLIB) $(MYSQLLIB) $(THREADLIB) -L$(LIBDIR) \
-lmysqlclient -lm
C_OBJECTS = main.o \
json.o \
ecs_config.o \
ecs_debug.o \
######### define target #########
all: $(TARGET)
main.o: main.c
$(CC) -W -Wall -Wextra -c $(CFLAGS) $(DEFINES) main.c
json.o: json.c
$(CC) -W -Wall -Wextra -c $(CFLAGS) $(DEFINES) json.c
config.o: config.c
$(CC) -W -Wall -Wextra -c $(CFLAGS) $(DEFINES) config.c
debug.o: debug.c
$(CC) -W -Wall -Wextra -c $(CFLAGS) $(DEFINES) debug.c
$(TARGET): $(C_OBJECTS)
$(CC) $(CFLAGS) $(DEFINES) -std=gnu99 -o $(TARGET) $(C_OBJECTS) $(LDFLAGS)
$(MV) *.o $(OBJ_DIR)
touch:
$(TOUCH) *.c
clean:
$(RM) $(OBJ_DIR)/*.o
rm -f *.o core $(TARGET)
cp:
cp -f $(TARGET) $(BINDIR)/$(TARGET)
so this make file is actually made by someone else from the group, and I cant really show the exact path to stuff, but hope this help
First of all, running the same make/makefile in parallel with different instances of make can result in race conditions -- so no, it's not a good idea. (eg. if instance 1 of make was trying to access a dependency that instance 2 was in the process of updating, you could end up with corrupt data)
That being said, you can get around that by just using a single instance of make as so:
make -j targ1 targ2 targ3
This will build targ1, targ2, and targ3, will build dependencies only once for all targets, and will build everything in the correct order etc.
I'm not clear why you would want to call this from a c file rather than just use the command line, but if there is a reason for this, you would want it to look something like:
char command[1024] = "";
char *eo_command = command + sizeof(command);
char *ptr = command;
ptr += snprintf(command, sizeof(command) "make -C %s", "file/path/");
// add some checks to ptr here...
for (int j = 0; tmp2[j] != NULL; j++) {
ptr += snprintf(ptr, eo_command-ptr, " %s", tmp2[j]);
// add some checks to ptr here...
}
system(command);
If you don't want to see the output, you can pipe the output to /dev/null. Also, if you want it to build faster, you can pass a -j flag to the make command line which will allow it to build multiple targets in parallel.
I'm going to close this question since the solution given by #Someprogrammerdude is the best fitting to my question I think.
So I did fix my problem by changing the code a little bit
for (int j = 0; tmp2[j] != NULL; j++)
{
printf("-> %s\n", tmp2[j]);
char command[128] = "";
sprintf(command, "make -C %s TARGET=%s all 2> make_error_log.txt > make_log.txt", "file/path/", tmp2[j]);
system(command);
}
Although, since Bodo mentioned it i'm going to learn shell scripting too.
Thanks for all the help
it is possible to call the make command with a & at the end, so the process spawns in the background, and you get the PID.
Something like that:
make -SOME_FLAGS &
I've .c files in different subfolders within main src directory, I've the problem with running Makefile, I'm new to Makefile, need hands on the Makefile to work and to create a static library.
src/math/addition/add.c (+add.h)
int add(int a, int b) {return a + b;}
src/math/subtraction/sub.c (+sub.h)
int sub(int a, int b) {return a - b;}
src/math/math.c
#include "addition/add.h"
#include "subtraction/sub.h"
Makefile (at the root of the project)
SRC=src/math/Math.c src/math/Math.h src/math/addition/add.c src/math/addition/add.h src/math/subtraction/sub.c src/math/subtraction/sub.h
INCLUDE_PATH=src/
Math: bin
ar rcs libMath.a Math.o
bin:
mkdir bin/
for dir in $(SRC); do \
cd $$dir; \
gcc -c *.c -I../; \
mv *.o ../../../bin; \
cd -; \
done
If you believe there's a better way or any lateral thinking, I'm not fixated on anything.
Makefile is good at two things: building dependency graphs and executing steps between each node in the dependency graphs.
If you have access to GNUMake (most of us do; it's pretty much the only one anyone uses), you can use VPATH to tidy up a bit. VPATH is used to tell make where it can find source files. Be careful with it, if you have multiple files with the same name under different directories.
I suggest you use something akin to the following
VPATH := src src/math src/math/addition src/math/subtraction
CFLAGS += -Isrc -Isrc/math -Isrc/mathaddition -Isrc/math/subtraction
all: libMath
libMath: bin/Math.o bin/add.o bin/sub.o
ar rcs libMath bin/Math.o bin/add.o bin/sub.o
bin/%.o: %.c %.h
Make contains a default .c -> .o rule which you can use; the %.o: %.c %.hdoes this, but also declares that all .o files, by default, depend on a .c and a .h file with the same prefix (the % part) as the object file.
I suspect your Math.o target will also depend on the addition.h and subtraction.h files; you can declare Math.o as dependent on those files using the rule Math.o: Math.c Math.h addition.h subtraction.h.
Remember to substitute the space before ar, with a tab.
You may want to change how you organize your source files and/or header files.
Usually ar produces archive files that end in .a. You may want to change that as well.
If you use make right, you can use parallel builds (make -J) to really speed up compilation time; if you use it wrong, everything is going to get slower and we'll have yet another person who starts to hate make because they don't understand it.
Makefile:
#
# Boilerplate.
#
all:
define add_target
$(info add_target($1))
$(eval $(eval_args))
$(eval $(call eval_args,$1,\
OBJDIR := $(firstword $($1.OBJDIR) ./objs/$1),\
))
$(eval $(call eval_args,$1,\
TYPE := $(firstword $($1.TYPE) binary),\
))
$(eval $(call eval_args,$1,\
objs := $(obj_from_source),
))
$(eval $1 := $($1.TARGET))
TARGETS += $($1)
PHONY_TARGETS += $1
CLEAN_TARGETS += clean_$1
.PHONY: clean_$1
clean_$1:; rm -rf $($1.OBJDIR) $($1)
.PHONY: $1
$1: $($1)
$($1): target:=$1
$($1): $($1.objs); $$(if $$(wildcard $$(#D)),,mkdir -p $$(#D) && )$$(add_target.link)
$($1.objs):; $$(if $$(wildcard $$(#D)),,mkdir -p $$(#D) && )$$(add_target.compile)
$(foreach $1.SOURCES,$($1.SOURCES),$(eval $(obj_from_source): $($1.SOURCES)))
$(info end)
endef
void :=
space := $(void) $(void)
obj_from_source = $(addprefix $($1.OBJDIR)/,$(addsuffix .o,$(basename $(notdir $($1.SOURCES)))))
eval_args = $(foreach i,2 3 4 5 6 7 8 9,$(call eval_arg,$1,$(strip $($i))))
eval_arg = $(if $2,$(info $(space)$(space)$1.$2)$(eval $1.$2))
# Link command line
add_target.link_binary = $(CC) $($(target).LDFLAGS) -o $# $^
add_target.link_lib = $(AR) rcs $# $^
add_target.link = $(add_target.link_$($(target).TYPE))
# Compile command line
add_target.compile = $(CC) -c -o $# $($(target).CFLAGS) $<
# -- Directories --
SRC_ROOT := ./src
BIN := ./bin
# Add 'math' target to the project
$(eval $(call add_target,math,\
TYPE := lib,\
TARGET := $(BIN)/math.a,\
SOURCES += ${SRC_ROOT}/math/addition/add.c\
${SRC_ROOT}/math/subtraction/sub.c\
${SRC_ROOT}/math/math.c,\
CFLAGS := -Wall -I./$(SRC_ROOT)/math,\
))
all: ${PHONY_TARGETS}
.PHONY: all
clean: | $(CLEAN_TARGETS)
.PHONY: clean
Directory structure:
$ find
.
./Makefile
./src
./src/math
./src/math/addition
./src/math/addition/add.c
./src/math/addition/add.h
./src/math/math.c
./src/math/subtraction
./src/math/subtraction/sub.c
./src/math/subtraction/sub.h
File contents:
$ find src/ -type f -exec sh -c "echo Contents of {} file:; cat {}; echo" \;
Contents of src/math/addition/add.c file:
int add(int a, int b) {return a + b;}
Contents of src/math/addition/add.h file:
int add(int a, int b);
Contents of src/math/math.c file:
#include "addition/add.h"
#include "subtraction/sub.h"
Contents of src/math/subtraction/sub.c file:
int add(int a, int b) {return a - b;}
Contents of src/math/subtraction/sub.h file:
int add(int a, int b);
Running Makefile:
$ make
add_target(math)
math.TYPE := lib
math.TARGET := ./bin/math.a
math.SOURCES += ./src/math/addition/add.c ./src/math/subtraction/sub.c ./src/math/math.c
math.CFLAGS := -Wall -I././src/math
math.OBJDIR := ./objs/math
math.TYPE := lib
math.objs := ./objs/math/add.o ./objs/math/sub.o ./objs/math/math.o
end
mkdir -p objs/math && cc -c -o objs/math/add.o -Wall -I././src/math src/math/addition/add.c
cc -c -o objs/math/sub.o -Wall -I././src/math src/math/subtraction/sub.c
cc -c -o objs/math/math.o -Wall -I././src/math src/math/math.c
mkdir -p bin && ar rcs bin/math.a objs/math/add.o objs/math/sub.o objs/math/math.o
This general purpose makefile is missing some important features, like tracking .h file dependencies, linking with static/dynamic libraries, etc. Extend it with the features you need yourself.
I've noticed a lot of questions about people having the message "make: Nothing to be done for 'all'.", however my problem is the opposite.
Here is my makefile:
#################
## VARIABLES ##
#################
# Environment
OS := $(shell uname)
# Output
NAME := libft.a
DYNAMIC_NAME := ${NAME:a=so}
# Compiler
CC := gcc
ifneq ($(OS), Linux)
FLAGS += -Wall -Wextra -Werror
endif
DYN_FLAG := -shared
HEADERS := -I ./includes/
O_FLAG := -O2
# Directories
ADDITIONAL_FUNCTIONS = $(addprefix ./additional_functions/, $(ADDITIONAL))
BONUS_FUNCTIONS = $(addprefix ./bonus_functions/, $(BONUS))
LIBC_FUNCTIONS = $(addprefix ./libc_functions/, $(LIBC))
PERSONAL_FUNCTIONS = $(addprefix ./personal_functions/, $(PERSONAL))
DYN_OBJDIR = dyn_build/
OBJDIR := build/
# Sources
ADDITIONAL += ft_itoa.c
ADDITIONAL += ft_memalloc.c ft_memdel.c
ADDITIONAL += ft_putchar.c ft_putchar_fd.c
ADDITIONAL += ft_putendl.c ft_putendl_fd.c
ADDITIONAL += ft_putnbr.c ft_putnbr_fd.c
ADDITIONAL += ft_putstr.c ft_putstr_fd.c
ADDITIONAL += ft_strclr.c ft_strdel.c
ADDITIONAL += ft_strnew.c ft_strjoin.c
ADDITIONAL += ft_strequ.c ft_strnequ.c
ADDITIONAL += ft_striter.c ft_striteri.c
ADDITIONAL += ft_strmap.c ft_strmapi.c
ADDITIONAL += ft_strsplit.c ft_strsub.c ft_strtrim.c
BONUS += ft_lstadd.c ft_lstnew.c
BONUS += ft_lstdel.c ft_lstdelone.c
BONUS += ft_lstiter.c ft_lstmap.c
LIBC += ft_atoi.c
LIBC += ft_isalnum.c ft_isalpha.c ft_isascii.c
LIBC += ft_isdigit.c ft_isprint.c
LIBC += ft_memcpy.c ft_memccpy.c ft_memchr.c ft_memcmp.c
LIBC += ft_bzero.c ft_memmove.c ft_memset.c
LIBC += ft_strcat.c ft_strlcat.c ft_strncat.c
LIBC += ft_strchr.c ft_strrchr.c
LIBC += ft_strcmp.c ft_strncmp.c
LIBC += ft_strcpy.c ft_strncpy.c ft_strdup.c
LIBC += ft_strlen.c
LIBC += ft_strstr.c ft_strnstr.c
LIBC += ft_tolower.c ft_toupper.c
PERSONAL += ft_intlen.c
PERSONAL += ft_invert.c ft_islower.c ft_isupper.c
PERSONAL += ft_lstgetnode.c ft_lstsize.c
PERSONAL += ft_kill.c ft_putuchar.c ft_putuchar_fd.c
PERSONAL += ft_strrev.c ft_strrevcpy.c
PERSONAL += get_next_line.c
DYN_OBJECTS = $(patsubst %.c,$(DYN_OBJDIR)%.o,$(SRCS))
OBJECTS = $(patsubst %.c,$(OBJDIR)%.o,$(SRCS))
SRCS += $(ADDITIONAL_FUNCTIONS)
SRCS += $(BONUS_FUNCTIONS)
SRCS += $(LIBC_FUNCTIONS)
SRCS += $(PERSONAL_FUNCTIONS)
#################
## RULES ##
#################
all: $(NAME)
$(NAME): $(OBJECTS)
#ar rcs $# $(patsubst %.c,$(OBJDIR)%.o,$(notdir $(SRCS)))
ranlib $#
#echo "Static library created."
$(OBJECTS): | $(OBJDIR)
$(OBJDIR):
#mkdir -p $#
$(OBJDIR)%.o: %.c
$(CC) $(FLAGS) $(O_FLAG) -c $< $(HEADERS) -o $(OBJDIR)$(notdir $#)
$(DYN_OBJECTS): | $(DYN_OBJDIR)
$(DYN_OBJDIR):
#mkdir -p $#
$(DYN_OBJDIR)%.o: %.c
$(CC) $(FLAGS) $(O_FLAG) -c $< $(HEADERS) -fpic -o $(DYN_OBJDIR)$(notdir $#)
clean:
#/bin/rm -rfv $(OBJDIR)
#/bin/rm -rfv $(DYN_OBJDIR)
fclean: clean
#/bin/rm -fv $(NAME)
#/bin/rm -fv $(DYNAMIC_NAME)
re: fclean all
so: $(DYN_OBJECTS)
#$(CC) $(DYN_FLAG) -o $(DYNAMIC_NAME) $(patsubst %.c,$(DYN_OBJDIR)%.o,$(notdir $(SRCS)))
#echo "Dynamic library created."
.PHONY: all build clean dynbuild fclean re so
The makefile works perfectly fine. It takes every .c in the different directories, creates an object directory, build/ if the library is static and dyn_build/ if it is dynamic, put the object files inside said directory and compile the library from them.
My issue is that if I run make twice in a row, nothing should be done the second time as the object files and the library are still there and up to date. But, somehow doing make twice in a row results in the second make repeating the operation.
What is causing this and is there a way to fix it?
Your problem can be reduced to this:
ADDITIONAL += ft_strsplit.c
BONUS += ft_lstadd.c
ADDITIONAL_FUNCTIONS = $(addprefix ./add/, $(ADDITIONAL))
BONUS_FUNCTIONS = $(addprefix ./bonus/, $(BONUS))
SRCS += $(ADDITIONAL_FUNCTIONS)
SRCS += $(BONUS_FUNCTIONS)
OBJECTS = $(patsubst %.c,./build/%.o,$(SRCS))
# OBJECTS contains ./build/./add/ft_strsplit.o and ./build/./bonus/ft_lstadd.o
all: $(OBJECTS)
$(OBJDIR)%.o: %.c
$(CC) ...
So Make runs the last rule with e.g. build/./add/ft_strsplit.o as the target, and add/ft_strsplit.c as the prerequisite. The question is how to write the recipe so as to build build/ft_strsplit.o.
As #user657267 has pointed out, it is a mistake to have a (non-PHONY) rule that does not build a file whose name is the target of the rule. So let's first ask Make for the files we actually want:
ADDITIONAL += ft_strsplit.c
BONUS += ft_lstadd.c
SRCS += $(ADDITIONAL)
SRCS += $(BONUS)
OBJECTS = $(patsubst %.c,./build/%.o,$(SRCS))
# OBJECTS contains ./build/ft_strsplit.o and ./build/ft_lstadd.o
So far so good, but now how can Make find the sources? When we ask Make to build ./build/ft_strsplit.o, how can it know where ft_strsplit.c is?
We use vpath:
vpath %.c add bonus
Now the makefile works correctly. And to write that vpath line automatically, we can just pull the directory names out of the assignments:
# Directories
ADDITIONAL_DIR := ./additional_functions
BONUS_DIR := ./bonus_functions
...
ADDITIONAL_FUNCTIONS = $(addprefix $(ADDITIONAL_DIR)/, $(ADDITIONAL))
BONUS_FUNCTIONS = $(addprefix $(BONUS_DIR)/, $(BONUS))
...
vpath %.c $(ADDITIONAL_DIR)
vpath %.c $(BONUS_DIR)
...
I have some problems with double! Through terminal there is some query, that I should give some number (For example how much delay in per hour). If I give through terminal a number such as 1.1 h then it prints about -1173000! It should print only 1.1.
I think, maybe there is some problem with the Makefile from FreeRTOS. (because it doesn't compile through FreeRTOS to STM32F407 processor!)
I believe something on this line should be fixed!
CPU = -mcpu=cortex-m4 -mthumb -mfloat-abi=softfp -mfpu=fpv4-sp-d16
Here is the complete code of Makefile:
# Optimization level, can be [0, 1, 2, 3, s].
# 0 = turn off optimization. s = optimize for size.
#
OPT = 0
# Object files directory
# Warning: this will be removed by make clean!
#
OBJDIR = obj
# Target file name (without extension)
#TARGET = $(OBJDIR)/main
TARGET = $(OBJDIR)/STM32F4_Test
# Define all C source files (dependencies are generated automatically)
#
SOURCES += src/uart.c
SOURCES += src/ustime.c
SOURCES += src/main.c
SOURCES += src/startup_stm32f4xx.S
SOURCES += src/system_stm32f4xx.c
SOURCES += src/syscalls.c
SOURCES += src/modbus.c
SOURCES += src/test.c
SOURCES += src/get.c
SOURCES += src/heap_2.c
SOURCES += FreeRTOS/Source/tasks.c
SOURCES += FreeRTOS/Source/queue.c
SOURCES += FreeRTOS/Source/list.c
SOURCES += FreeRTOS/Source/croutine.c
SOURCES += FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c
SOURCES += libs/STM32F4xx_StdPeriph_Driver/src/misc.c
SOURCES += libs/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_adc.c
SOURCES += libs/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_can.c
SOURCES += libs/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_crc.c
SOURCES += libs/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_cryp.c
SOURCES += libs/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_cryp_aes.c
SOURCES += libs/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_cryp_des.c
SOURCES += libs/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_cryp_tdes.c
SOURCES += libs/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_dac.c
SOURCES += libs/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_dbgmcu.c
SOURCES += libs/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_dcmi.c
SOURCES += libs/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_dma.c
SOURCES += libs/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_exti.c
SOURCES += libs/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_flash.c
SOURCES += libs/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_fsmc.c
SOURCES += libs/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_gpio.c
SOURCES += libs/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_hash.c
SOURCES += libs/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_hash_md5.c
SOURCES += libs/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_hash_sha1.c
SOURCES += libs/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_i2c.c
SOURCES += libs/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_iwdg.c
SOURCES += libs/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_pwr.c
SOURCES += libs/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_rcc.c
SOURCES += libs/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_rng.c
SOURCES += libs/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_rtc.c
SOURCES += libs/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_sdio.c
SOURCES += libs/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_spi.c
SOURCES += libs/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_syscfg.c
SOURCES += libs/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_tim.c
SOURCES += libs/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_usart.c
SOURCES += libs/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_wwdg.c
OBJECTS = $(addprefix $(OBJDIR)/,$(addsuffix .o,$(basename $(SOURCES))))
# Place -D, -U or -I options here for C and C++ sources
CPPFLAGS += -Isrc
CPPFLAGS += -IFreeRTOS/Source/include
CPPFLAGS += -Ilibs/CMSIS/Include
CPPFLAGS += -Ilibs/Device/STM32F4xx/Include
CPPFLAGS += -Ilibs/STM32F4xx_StdPeriph_Driver/inc
#---------------- Compiler Options C ----------------
# -g*: generate debugging information
# -O*: optimization level
# -f...: tuning, see GCC documentation
# -Wall...: warning level
# -Wa,...: tell GCC to pass this to the assembler.
# -adhlns...: create assembler listing
CFLAGS = -O$(OPT)
CFLAGS += -std=gnu99
CFLAGS += -gdwarf-2
CFLAGS += -ffunction-sections
CFLAGS += -fdata-sections
CFLAGS += -Wall
#CFLAGS += -Wextra
#CFLAGS += -Wpointer-arith
#CFLAGS += -Wstrict-prototypes
#CFLAGS += -Winline
#CFLAGS += -Wunreachable-code
#CFLAGS += -Wundef
CFLAGS += -Wa,-adhlns=$(OBJDIR)/$(*F).lst
# Optimize use of the single-precision FPU
#
# CFLAGS += -fsingle-precision-constant
# This will not work without recompiling libs
#
# CFLAGS += -fshort-double
#---------------- Compiler Options C++ ----------------
#
CXXFLAGS = $(CFLAGS)
#---------------- Assembler Options ----------------
# -Wa,...: tell GCC to pass this to the assembler
# -adhlns: create listing
#
ASFLAGS = -Wa,-adhlns=$(OBJDIR)/$(*F).lst
#---------------- Linker Options ----------------
# -Wl,...: tell GCC to pass this to linker
# -Map: create map file
# --cref: add cross reference to map file
LDFLAGS += -lm
LDFLAGS += -Wl,-Map=$(TARGET).map,--cref
LDFLAGS += -Wl,--gc-sections
LDFLAGS += -Tsrc/stm32_flash.ld
#============================================================================
# Define programs and commands
TOOLCHAIN = d:/Programme/CodeSourcery/Sourcery_2011_09_ARM_EABI/bin/arm-none-eabi
CC = $(TOOLCHAIN)-gcc
OBJCOPY = $(TOOLCHAIN)-objcopy
OBJDUMP = $(TOOLCHAIN)-objdump
SIZE = $(TOOLCHAIN)-size
NM = $(TOOLCHAIN)-nm
OPENOCD = D:\Tools\openocd-0.7.0\bin\openocd-0.7.0.exe
DOXYGEN = doxygen
STLINK = tools/ST-LINK_CLI.exe
MKDIR = d:\tools\unxutils\bin\mkdir.exe
ifeq (AMD64, $(PROCESSOR_ARCHITEW6432))
SUBWCREV = tools/SubWCRev64.exe
else
SUBWCREV = tools/SubWCRev.exe
endif
# Compiler flags to generate dependency files
GENDEPFLAGS = -MMD -MP -MF $(OBJDIR)/$(*F).d
# Combine all necessary flags and optional flags
# Add target processor to flags.
#
#CPU = -mcpu=cortex-m3 -mthumb -mfloat-abi=soft
#CPU = -mcpu=cortex-m4 -mthumb
#
// kannst du mal nach dem problem suchen? Und dich ueber floating point probleme informieren?
// auf der ARM cpu oder spezielle dieser F407 cpu
CPU = -mcpu=cortex-m4 -mthumb -mfloat-abi=softfp -mfpu=fpv4-sp-d16
#CPU = -mcpu=cortex-m4 -mthumb
CFLAGS += $(CPU)
CXXFLAGS += $(CPU)
ASFLAGS += $(CPU)
LDFLAGS += $(CPU)
# Default target.
all: setup gccversion build showsize
setup:
$(MKDIR) -p $(OBJDIR)
$(MKDIR) -p $(OBJDIR)\src
$(MKDIR) -p $(OBJDIR)\FreeRTOS\Source
$(MKDIR) -p $(OBJDIR)\FreeRTOS\Source\portable\GCC\ARM_CM4F
$(MKDIR) -p $(OBJDIR)\libs\STM32F4xx_StdPeriph_Driver\src
build: elf hex lss sym bin
elf: $(TARGET).elf
hex: $(TARGET).hex
bin: $(TARGET).bin
lss: $(TARGET).lss
sym: $(TARGET).sym
doxygen:
#echo
#echo Creating Doxygen documentation
#$(DOXYGEN)
# Display compiler version information
gccversion:
#$(CC) --version
# Show the final program size
showsize: elf
#echo
#$(SIZE) $(TARGET).elf
# debug level
OOCD_CL=-d2
#OOCD_CL=-d3
# interface and board/target settings (using the OOCD target-library here)
## OOCD_CL+=-c "fast enable"
OOCD_CL+=-f interface/signalyzer.cfg -f openocd/stm32f4x.cfg
OOCD_CL+=-f openocd/config.cfg
OOCD_CL+=-c init -c targets
# commands to prepare flash-write
OOCD_CL+=-c "halt"
# flash-write and -verify
OOCD_CL+=-c "flash write_image erase $(TARGET).elf" -c "verify_image $(TARGET).elf"
# reset target
OOCD_CL+=-c "reset run"
# terminate OOCD after programming
# OOCD_CL+=-c shutdown
# Flash the device
flash: hex
# $(OPENOCD) -f "interface/signalyzer.cfg" -f "openocd/stm32f4x.cfg" -f "openocd/config.cfg" -c "flash_image $(TARGET).elf; shutdown"
$(OPENOCD) $(OOCD_CL)
# $(STLINK) -c SWD -P $(TARGET).hex -Run
# Target: clean project
clean:
#echo Cleaning project:
rm -rf $(OBJDIR)
rm -rf docs/html
# Create extended listing file from ELF output file
%.lss: %.elf
#echo
#echo Creating Extended Listing: $#
$(OBJDUMP) -h -S -z $< > $#
# Create a symbol table from ELF output file
%.sym: %.elf
#echo
#echo Creating Symbol Table: $#
$(NM) -n $< > $#
# Link: create ELF output file from object files
.SECONDARY: $(TARGET).elf
.PRECIOUS: $(OBJECTS)
$(TARGET).elf: $(OBJECTS)
#echo
#echo Linking: $#
$(CC) $^ $(LDFLAGS) --output $#
# Create final output files (.hex, .eep) from ELF output file.
%.hex: %.elf
#echo
#echo Creating hex file: $#
$(OBJCOPY) -O ihex $< $#
# Create bin file :
%.bin: %.elf
#echo
#echo Creating bin file: $#
$(OBJCOPY) -O binary $< $#
# Compile: create object files from C source files
$(OBJDIR)/%.o : %.c
#echo
#echo Compiling C: $<
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(GENDEPFLAGS) $< -o $#
# Compile: create object files from C++ source files
$(OBJDIR)/%.o : %.cpp
#echo
#echo Compiling CPP: $<
$(CC) -c $(CPPFLAGS) $(CXXFLAGS) $(GENDEPFLAGS) $< -o $#
# Assemble: create object files from assembler source files
$(OBJDIR)/%.o : %.s
#echo
#echo Assembling: $<
$(CC) -c $(CPPFLAGS) $(ASFLAGS) $< -o $#
# Include the dependency files
-include $(wildcard $(OBJDIR)/*.d)
# Listing of phony targets
.PHONY: all build flash clean \
doxygen elf lss sym \
showsize gccversion \
build elf hex bin lss sym clean clean_list setup program
I don't believe the Sourcery CodeBench 2011.09 ARM EABI compiler supports that configuration. In particular, your FPU setting appears to use single-precision, and I'm pretty sure all the libraries included with that toolchain expect a double-precision FPU.
It's not that the compiler can't produce the code you ask for. The problem is that the toolchain doesn't include compatible libraries.
It's possible that I'm mistaken and the FreeRTOS folks have already built and bundled the missing pieces, but suspect not.
I am currently writing a short test app.
The compilation gives me these errors :
CC main.c
Building ../bin/pmono
./main.o:(.data+0x18): undefined reference to `busy'
./main.o:(.data+0x58): undefined reference to `busy'
./main.o:(.data+0x98): undefined reference to `busy'
./main.o:(.data+0xd8): undefined reference to `busy'
./main.o:(.data+0x118): undefined reference to `busy'
./main.o:(.data+0x158): more undefined references to `busy' follow
collect2: ld a retourné 1 code d'état d'exécution
I will try to narrow the code down to the specific parts.
Here is a structure I use which contain the desired reference :
/*
* Chained list of blocks from a frame of the cyclic executive
*/
typedef struct block {
long c; /* Worst case execution time */
long d; /* Deadline */
long p; /* Period */
void (*action) (long); /* Action performed by this frame */
struct block * next;
} *Frame;
The function pointer is placeholder for a generic function not written yet, declared as such in the same .h file :
/*
* Load the CPU for a determined time expressed in nanosecond
*/
void busy(long t);
The function is currently hollow in the c file :
void busy(long t) {
}
Finally, here is a sample default structure I use in my tests :
struct block D = {8,20,20,busy,0};
struct block C = {2,20,20,busy,&D};
struct block B = {3,10,10,busy,&C};
struct block A = {1,10,10,busy,&B};
Frame sequence0 = &A;
All of these parts are contained in a common source file shared between numerous implementations of periodic tasks. The compilation of the object file seems fine.
When I try to compile a given implementation, I first include the .h file, compile the .o file, then try to link the whole thing, using makefile. Here is one makefile to give you an idea :
BIN = ../bin/pmono
CC = gcc
SUBDIR = .
SRC = $(foreach dir, $(SUBDIR), $(wildcard $(dir)/*.c))
OBJ = $(SRC:.c=.o) $(wildcard ../common/*.o)
INCLUDES =
WARNINGS =
OPTIMISATION =
DEBUG =
XENO_CONFIG = /usr/xenomai/bin/xeno-config
XENO_POSIX_CFLAGS = $(shell $(XENO_CONFIG) --skin=posix --cflags)
XENO_POSIX_LDFLAGS = $(shell $(XENO_CONFIG) --skin=posix --ldflags)
CFLAGS = $(INCLUDES) $(XENO_POSIX_CFLAGS) $(WARNINGS) $(OPTIMISATION)
LDFLAGS = -lm $(XENO_POSIX_LDFLAGS) $(DEBUG)
all:.depend $(BIN)
%.o:%.c
#echo "CC $<"
#$(CC) -c $(CFLAGS) $< -o $#
$(BIN): $(OBJ)
#echo "Building ${BIN}"
#$(CC) $(OBJ) -o $# $(LDFLAGS)
clean:
rm -f $(OBJ)
distclean: clean
rm -f $(BIN)
rm -f ./.depend
.depend: $(SRC)
#echo "Génération des dépendances"
#$(CC) $(CFLAGS) -MM $(SRC) > .depend
-include .depend
So, I'm a beginner in this, and this is my understanding : the symbol of the busy function is missing in the main.o, while it exists in the cyclic_executive.o file. I don't understand how this is possible, as I include the cyclic_executive.h file, thus giving the proper declaration and prototype.
I think I'm doing it wrong, but I'm short on idea.
Also, I really dislike how I declare my "default" sequence. I know there is a proper way to do it, but I can't recall it... Does someone has a name to help search for it ?
Thanks.
You are not linking the file with the busy() function call.
Try this from the command line:
gcc main.c cyclic_executive.c
If it works, or at least doesn't give errors on the busy() function, that will confirm the issue. Then try
make all
This should print all the commands as they are executed. If you are still in the dark, try
make -d
That will give you a ton of diagnostics about what make is actually doing.