This question is a repex created corresponding to this problem.
In my embedded C project I have two separate boards and I want to create two .c files (master.c and slave.c) for each board containing their own specific main() function.
I've used stm32cumbemx to generate the project with main.c, makefile and other sources and headers (I want to replace main.c with master.c and slave.c manually).
this is the folder structure of the project (I deleted slave.c for simplicity):
.
├── Inc
│ └── main.h
├── Makefile
├── Src
│ ├── main.c
│ └── master.c
└── STM32F103RBTx_FLASH.ld
main.h:
#ifndef __MAIN_H
#define __MAIN_H
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /* __MAIN_H */
main.c:
#include "main.h"
int variable = 1;
void function(void);
int main() {
variable += 1;
while(1){}
}
void function(void) {
int something = 0;
something++;
}
master.c:
#include "main.h"
int variable = 1;
int variable2;
void function(void);
void function2(void);
int main() {
variable += 1;
while(1){
function2();
}
}
void function(void) {
int something = 0;
something++;
}
void function2(void) {
variable2++;
}
STM32F103RBTx_FlASH.ld:
/* Entry Point */
ENTRY(Reset_Handler)
/* Highest address of the user mode stack */
_estack = 0x20005000; /* end of RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x200; /* required amount of heap */
_Min_Stack_Size = 0x400; /* required amount of stack */
/* Specify the memory areas */
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 128K
}
/* Define output sections */
SECTIONS
{
/* The startup code goes first into FLASH */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >FLASH
/* The program code and other data goes into FLASH */
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
*(.eh_frame)
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
_etext = .; /* define a global symbols at end of code */
} >FLASH
/* Constant data goes into FLASH */
.rodata :
{
. = ALIGN(4);
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
. = ALIGN(4);
} >FLASH
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
.ARM : {
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} >FLASH
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >FLASH
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array*))
PROVIDE_HIDDEN (__init_array_end = .);
} >FLASH
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array*))
PROVIDE_HIDDEN (__fini_array_end = .);
} >FLASH
/* used by the startup to initialize data */
_sidata = LOADADDR(.data);
/* Initialized data sections goes into RAM, load LMA copy after code */
.data :
{
. = ALIGN(4);
_sdata = .; /* create a global symbol at data start */
*(.data) /* .data sections */
*(.data*) /* .data* sections */
. = ALIGN(4);
_edata = .; /* define a global symbol at data end */
} >RAM AT> FLASH
/* Uninitialized data section */
. = ALIGN(4);
.bss :
{
/* This is used by the startup in order to initialize the .bss secion */
_sbss = .; /* define a global symbol at bss start */
__bss_start__ = _sbss;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .; /* define a global symbol at bss end */
__bss_end__ = _ebss;
} >RAM
/* User_heap_stack section, used to check that there is enough RAM left */
._user_heap_stack :
{
. = ALIGN(8);
PROVIDE ( end = . );
PROVIDE ( _end = . );
. = . + _Min_Heap_Size;
. = . + _Min_Stack_Size;
. = ALIGN(8);
} >RAM
/* Remove information from the standard libraries */
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
.ARM.attributes 0 : { *(.ARM.attributes) }
}
and makefile (the parts I added to pre-generated file are between #edit begin and #edit end comments:
TARGET = myproject
#edit begin
MASTER = master
SLAVE = slave
#edit end
DEBUG = 1
# optimization
OPT = -Og
BUILD_DIR = build
# C sources
C_SOURCES = \
Src/main.c
#edint begin
SLAVE_SOURCES = \
Src/slave.c
MASTER_SOURCES = \
Src/master.c \
#edit end
PREFIX = arm-none-eabi-
# The gcc compiler bin path can be either defined in make command via GCC_PATH variable (> make GCC_PATH=xxx)
# either it can be added to the PATH environment variable.
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
CPU = -mcpu=cortex-m3
# fpu
# NONE for Cortex-M0/M0+/M3
# float-abi
# mcu
MCU = $(CPU) -mthumb $(FPU) $(FLOAT-ABI)
# macros for gcc
# AS defines
AS_DEFS =
# C defines
C_DEFS = \
-DUSE_HAL_DRIVER \
-DSTM32F103xB
# AS includes
AS_INCLUDES =
# C includes
C_INCLUDES = \
-IInc \
# compile gcc flags
ASFLAGS = $(MCU) $(AS_DEFS) $(AS_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections
CFLAGS = $(MCU) $(C_DEFS) $(C_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections
ifeq ($(DEBUG), 1)
CFLAGS += -g -gdwarf-2
endif
# Generate dependency information
CFLAGS += -MMD -MP -MF"$(#:%.o=%.d)"
# link script
LDSCRIPT = STM32F103RBTx_FLASH.ld
# libraries
LIBS = -lc -lm -lnosys
LIBDIR =
LDFLAGS = $(MCU) -specs=nano.specs -T$(LDSCRIPT) $(LIBDIR) $(LIBS) -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref -Wl,--gc-sections
# default action: build all
all: $(BUILD_DIR)/$(TARGET).elf $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).bin
#edit begin
master: $(BUILD_DIR)/$(MASTER).elf $(BUILD_DIR)/$(MASTER).hex $(BUILD_DIR)/$(MASTER).bin
slave: $(BUILD_DIR)/$(SLAVE).elf $(BUILD_DIR)/$(SLAVE).hex $(BUILD_DIR)/$(SLAVE).bin
#edit end
#######################################
# 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)))
$(info OBJECTS is $(OBJECTS))
#edit begin
MASTER_OBJ = $(addprefix $(BUILD_DIR)/,$(notdir $(MASTER_SOURCES:.c=.o)))
vpath %.c $(sort $(dir $(MASTER_SOURCES)))
$(info MASTER_OBJ is $(MASTER_OBJ))
MASTER_OBJ += $(addprefix $(BUILD_DIR)/,$(notdir $(ASM_SOURCES:.s=.o)))
vpath %.s $(sort $(dir $(ASM_SOURCES)))
#edit end
$(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) $#
#edit begin
$(BUILD_DIR)/$(MASTER).elf: $(MASTER_OBJ) Makefile
$(CC) $(MASTER_OBJ) $(LDFLAGS) -o $#
$(SZ) $#
$(BUILD_DIR)/$(SLAVE).elf: $(SLAVE_OBJ) Makefile
$(CC) $(SLAVE_OBJ) $(LDFLAGS) -o $#
$(SZ) $#
#edit end
$(BUILD_DIR)/%.hex: $(BUILD_DIR)/%.elf | $(BUILD_DIR)
$(HEX) $< $#
$(BUILD_DIR)/%.bin: $(BUILD_DIR)/%.elf | $(BUILD_DIR)
$(BIN) $< $#
$(BUILD_DIR):
mkdir $#
clean:
-rm -fR $(BUILD_DIR)
-include $(wildcard $(BUILD_DIR)/*.d)
# *** EOF ***
resutlt of sudo make in terminal:
OBJECTS is build/main.o
MASTER_OBJ is build/master.o
mkdir build
arm-none-eabi-gcc -c -mcpu=cortex-m3 -mthumb -DUSE_HAL_DRIVER -DSTM32F103xB -IInc -Og -Wall -fdata-sections -ffunction-sections -g -gdwarf-2 -MMD -MP -MF"build/main.d" -Wa,-a,-ad,-alms=build/main.lst Src/main.c -o build/main.o
arm-none-eabi-gcc build/main.o -mcpu=cortex-m3 -mthumb -specs=nano.specs -TSTM32F103RBTx_FLASH.ld -lc -lm -lnosys -Wl,-Map=build/myproject.map,--cref -Wl,--gc-sections -o build/myproject.elf
arm-none-eabi-size build/myproject.elf
text data bss dec hex filename
88 8 1568 1664 680 build/myproject.elf
arm-none-eabi-objcopy -O ihex build/myproject.elf build/myproject.hex
arm-none-eabi-objcopy -O binary -S build/myproject.elf build/myproject.bin
as you see the code compiles with no errors.
and result of sudo make master (after running sudo make clean):
MASTER_OBJ is build/master.o
mkdir build
arm-none-eabi-gcc -c -mcpu=cortex-m3 -mthumb -DUSE_HAL_DRIVER -DSTM32F103xB -IInc -IDrivers/STM32F1xx_HAL_Driver/Inc -IDrivers/STM32F1xx_HAL_Driver/Inc/Legacy -IDrivers/CMSIS/Device/ST/STM32F1xx/Include -IDrivers/CMSIS/Include -Og -Wall -fdata-sections -ffunction-sections -g -gdwarf-2 -MMD -MP -MF"build/master.d" -Wa,-a,-ad,-alms=build/master.lst Src/master.c -o build/master.o
arm-none-eabi-gcc build/master.o -mcpu=cortex-m3 -mthumb -specs=nano.specs -TSTM32F103RBTx_FLASH.ld -lc -lm -lnosys -Wl,-Map=build/dual-interface.map,--cref -Wl,--gc-sections -o build/master.elf
c:/program files (x86)/gnu arm embedded toolchain/10 2021.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld.exe: warning: cannot find entry symbol Reset_Handler; defaulting to 08000000
arm-none-eabi-size build/master.elf
text data bss dec hex filename
88 8 1568 1664 680 build/master.elf
arm-none-eabi-objcopy -O ihex build/master.elf build/master.hex
arm-none-eabi-objcopy -O binary -S build/master.elf build/master.bin
arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -DUSE_HAL_DRIVER -DSTM32F103xB -IInc -IDrivers/STM32F1xx_HAL_Driver/Inc -IDrivers/STM32F1xx_HAL_Driver/Inc/Legacy -IDrivers/CMSIS/Device/ST/STM32F1xx/Include -IDrivers/CMSIS/Include -Og -Wall -fdata-sections -ffunction-sections -g -gdwarf-2 -MMD -MP -MF"master" -mcpu=cortex-m3 -mthumb -specs=nano.specs -TSTM32F103RBTx_FLASH.ld -lc -lm -lnosys -Wl,-Map=build/dual-interface.map,--cref -Wl,--gc-sections Src/master.c build/master.elf build/master.hex build/master.bin -o master
c:/program files (x86)/gnu arm embedded toolchain/10 2021.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld.exe: build/master.elf: in function `_init':
(.text+0x40): multiple definition of `_init'; c:/program files (x86)/gnu arm embedded toolchain/10 2021.10/bin/../lib/gcc/arm-none-eabi/10.3.1/thumb/v7-m/nofp/crti.o:(.init+0x0): first defined here
c:/program files (x86)/gnu arm embedded toolchain/10 2021.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld.exe: build/master.elf: in function `_fini':
(.text+0x4c): multiple definition of `_fini'; c:/program files (x86)/gnu arm embedded toolchain/10 2021.10/bin/../lib/gcc/arm-none-eabi/10.3.1/thumb/v7-m/nofp/crti.o:(.fini+0x0): first defined here
build/master.bin: file not recognized: file format not recognized
collect2.exe: error: ld returned 1 exit status
make: *** [master] Error 1
How can I solve this?
you can recreate the error in windows with "gnu make" and "arm-none-eabi-gcc" as compiler. in linux and in case of stdint.h error, you also need to install one of the packages mentioned here.
The last gcc run ...
arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -DUSE_HAL_DRIVER -DSTM32F103xB -IInc -Og -Wall -fdata-sections -ffunction-sections -g -gdwarf-2 -MMD -MP -MF"master" -mcpu=cortex-m3 -mthumb -specs=nano.specs -TSTM32F103RBTx_FLASH.ld -lc -lm -lnosys -Wl,-Map=build/myproject.map,--cref -Wl,--gc-sections Src/master.c build/master.elf build/master.hex -o master
... that generates the errors, is itself erroneous. Where does it come from?
Note the -o master at the end: there is no rule presented in the makefile whose recipe would produce such a compilation, but it is building a file with the same name, master, as the goal target. This is the result of the exercise of a built-in implicit rule for building an executable from a correspondingly-named C source file.
Several circumstances contribute to this.
A request is made to build target master. It is the goal target in this case, but it would also suffice for it to be a prerequisite of another target that make wants to build.
The makefile does not provide any recipe for building master.
There is a source file named master.c. Although it is in subdirectory Src, there is a %vpath directive that tells make to treat files in that directory as if they appeared in the project root directory.
Additionally,
The built-in rule is apparently including the declared prerequisites of target master (build/master.elf and build/master.hex) in the compilation command. This is not documented or standard for versions of make I've checked, and it is the reason for the multiple-definition errors: gcc is building an executable, so it provides standard _init and _fini functions, but the already-built executable build/master.elf that is included in the link also has these.
Since you don't actually want a file named master built, a good solution would be to declare that target phony:
.PHONY: master
That has several useful effects, but key for your purposes is that it causes the implicit rule search for that target to be skipped.
Related
I am trying to build an application manually using arm-none-eabi-gcc. The build goes fine but I get the following error during link time:
error: no memory region specified for loadable section `.bss'
No other errors nor warnings. Just the build's output and this error,
I ended up trying back to the most basic type of linker script file that still allows me to build my app. This is the simplest/simplified linker script I can use and stil leads to the above error message:
MEMORY
{
foo : ORIGIN = 0x50000000, LENGTH = 0xF0000000
}
SECTIONS
{
.sram :
{
__sram_bss_start = .;
*(.bss)
*(.bss*)
*(.text)
__sram_bss_end = .;
} > foo
}
That's the linker file. Nothing more, nothing less.
As you can see the .bss segment is clearly defined so it is not clear to me why the linker is complaining.
This is how I am building and linking:
...
SOURCES := source1.c
SOURCES += source2.c
...
OBJECTS := $(SOURCES:$(MYSRCDIR)/%.c=$(MYOBJDIR)/%.o)
LD_FLAGS := -nostartfiles
LD_FLAGS += -T linkerScript.ld
LD_FLAGS += --entry=Reset_Handler
LD_FLAGS += -Wl,-Map,"memoryMap.map"
LD_FLAGS += -mcpu=cortex-m7
LD_FLAGS += -mthumb
LD_FLAGS += -mlittle-endian
LD_FLAGS += -mfloat-abi=hard
LD_FLAGS += -mfpu=fpv5-sp-d16
LD_FLAGS += -specs=nano.specs
LD_FLAGS += -specs=nosys.specs
LD_FLAGS += -lc
LD_FLAGS += -lm
LD_FLAGS += -lgcc
LD_FLAGS += --sysroot="/usr/lib/arm-none-eabi/newlib"
#LD_FLAGS += --verbose
all: $(BIN)
$(BIN): $(OBJECTS)
$(CC) -o $# $^ $(LD_FLAGS)
$(OBJDIR)/%.o : $(SRCDIR)/%.c
#mkdir -p $(#D)
$(CC) $(INC) $(CFLAGS) -o $# -c $< $(DEFS)
```
Compiler & linker version:
$ arm-none-eabi-gcc -v
...
gcc version 9.2.1 20191025
$ arm-none-eabi-ld -v
GNU ld (2.34-4ubuntu1+13ubuntu1) 2.34
Did I misunderstand something here?
I expected the application to compile and link fine. I tried going through gnu's documentation to understand what I misunderstood. But no success so far.
UPDATE:
This linker file gets passed the aforementionned issue:
MEMORY
{
foo : ORIGIN = 0x50000000, LENGTH = 0xF0000000
}
SECTIONS
{
/* Works fine */
.sram : { *(.text) } > foo
.bss : { *(.bss) } > foo
/* Does not work */
/*
.text : { *(.text) } > foo
.sram : { *(.bss) } > foo
*/
}
So I presume it maybe somehow has issues with the sectionname .sram? Based on the information I could find online any sectionname can be given and this name is not dependent on any other definition/declaration/... elsewhere in the project
I'm working my way through The Little Book About OS Development, specifically the section on the framebuffer (linked). I'm able to successfully assemble, link, turn into an ISO file and boot pure assembly, but as soon as I try to link a compiled object file for my C code (called from my loader, which was written in assembly), the linker complains. Here's the output:
nasm -f elf loader.s -o loader.o
nasm -f elf out.s -o out.o
/usr/local/Cellar/gcc#6/6.4.0/bin/gcc-6 -m32 -nostdlib -nostdinc -fno-builtin -fno-stack-protector -nostartfiles -nodefaultlibs -Wall -Wextra -Werror -c framebuffer.c -o framebuffer.o
/usr/local/Cellar/gcc#6/6.4.0/bin/gcc-6 -m32 -nostdlib -nostdinc -fno-builtin -fno-stack-protector -nostartfiles -nodefaultlibs -Wall -Wextra -Werror -c kmain.c -o kmain.o
i386-unknown-linux-gnu-ld -T link.ld -melf_i386 loader.o out.o framebuffer.o kmain.o -o kernel.elf
framebuffer.o: file not recognized: File format not recognized
make: *** [kernel.elf] Error 1
I'm on a Mac, so as you can tell I've compiled a custom version of the GNU linker so that I can use linker scripts, and I've made sure to specify GCC 6 (the system default is 4.0). Anyway, here's my Makefile:
OBJECTS = loader.o out.o framebuffer.o kmain.o
CC = /usr/local/Cellar/gcc#6/6.4.0/bin/gcc-6
CFLAGS = -m32 -nostdlib -nostdinc -fno-builtin -fno-stack-protector \
-nostartfiles -nodefaultlibs -Wall -Wextra -Werror -c
LDFLAGS = -T link.ld -melf_i386
AS = nasm
ASFLAGS = -f elf
all: kernel.elf
kernel.elf: $(OBJECTS)
i386-unknown-linux-gnu-ld $(LDFLAGS) $(OBJECTS) -o kernel.elf
os.iso: kernel.elf
cp kernel.elf iso/boot/kernel.elf
mkisofs -R \
-b boot/grub/stage2_eltorito \
-no-emul-boot \
-boot-load-size 4 \
-A os \
-input-charset utf8 \
-quiet \
-boot-info-table \
-o os.iso \
iso
run: os.iso
bochs -f bochsrc.txt -q
%.o: %.c
$(CC) $(CFLAGS) $< -o $#
%.o: %.s
$(AS) $(ASFLAGS) $< -o $#
clean:
rm -rf *.o kernel.elf os.iso
Here's my linker script:
ENTRY(loader) /* the name of the entry label */
SECTIONS {
. = 0x00100000; /* the code should be loaded at 1 MB */
.text ALIGN (0x1000) : /* align at 4 KB */
{
*(.text) /* all text sections from all files */
}
.rodata ALIGN (0x1000) : /* align at 4 KB */
{
*(.rodata*) /* all read-only data sections from all files */
}
.data ALIGN (0x1000) : /* align at 4 KB */
{
*(.data) /* all data sections from all files */
}
.bss ALIGN (0x1000) : /* align at 4 KB */
{
*(COMMON) /* all COMMON sections from all files */
*(.bss) /* all bss sections from all files */
}
}
Any help would be appreciated.
As it turns out, this was solved by cross-compiling GNU Binutils and GCC together (with the same prefix) on my Mac. I did this according to the instructions here.
I'm encountering an error that is doubtless due to some limit of my knowledge on how linkers work. Some ANSI C code I've written that compiles and links perfectly well on my OS X box fails to link with arm-none-eabi-ld when cross-compiled for ARM.
Here's the result from a clean make (with --verbose on ld):
arm-none-eabi-gcc -o build/fft.o src/fft.c -g -mthumb -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -Os -ffunction-sections -fdata-sections -MD -std=c99 -Wall -pedantic -DPART_TM4C123GH6PM -c -I../tivaware -DTARGET_IS_BLIZZARD_RA1
arm-none-eabi-gcc -o build/main.o src/main.c -g -mthumb -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -Os -ffunction-sections -fdata-sections -MD -std=c99 -Wall -pedantic -DPART_TM4C123GH6PM -c -I../tivaware -DTARGET_IS_BLIZZARD_RA1
arm-none-eabi-ld -o build/a.out build/fft.o build/main.o --verbose -T TM4C123GH6PM.ld --entry main --gc-sections
GNU ld (32-bit ARM EABI Toolchain JBS-FLOAT_IO-SGXXLITE_ML-2014.05-28-v2013.05-36-g3f93944) 2.24.51.20140217
Supported emulations:
armelf
opened script file TM4C123GH6PM.ld
using external linker script:
==================================================
MEMORY
{
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000
SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0X00008000
}
SECTIONS
{
/* code */
.text :
{
_text = .;
/* ensure ISR vectors are not removed by linker */
KEEP(*(.isr_vector))
*(.text*)
*(.rodata*)
_etext = .;
} > FLASH
/* static data */
.data : AT(ADDR(.text) + SIZEOF(.text))
{
_data = .;
*(vtable)
*(.data*)
_edata = .;
} > SRAM
/* static uninitialized data */
.bss :
{
_bss = .;
*(.bss*)
*(COMMON)
_ebss = .;
} > SRAM
}
==================================================
attempt to open build/fft.o succeeded
build/fft.o
attempt to open build/main.o succeeded
build/main.o
build/fft.o: In function `dft':
/path/src/fft.c:97: undefined reference to `calloc'
There's a number of other undefined symbols (__aeabi_dadd, __muldc3), which I've truncated for brevity.
Microcontrollers usually (practical reasons) are not configured with dynamic memory allocation facility.
so, malloc, calloc, free will not be available.
Recommendation: use static array to allocate memory.
even after reading this you need dynamic memory allocation, you can use newlibc
but beware that in case your heap and stack overlap, you will be in problem.
This is the command line executed by my Makefile:
arm-none-eabi-gcc bubblesort.c -O0 -mcpu=cortex-m0 -mthumb -Wl, -T ../boot_and_link/linker.ld -l ../boot_and_link/startup.o
As I understand it, it should compile bubblesort.c for a CortexM0 and then the linker should you use linker.ld as a linker script and should also link startup.o with the output of compiling bubblesort.c.
I get two errors:
/usr/lib/gcc/arm-none-eabi/4.8/../../../arm-none-eabi/bin/ld: cannot find : No such file or directory
/usr/lib/gcc/arm-none-eabi/4.8/../../../arm-none-eabi/bin/ld: cannot find -l../boot_and_link/startup.o
The first one I don't understand. ld tells me it cannot find : which makes no sense and makes me think there an error in my linker script.
The second error is just weird because my linker file is in the exact same location and it finds it and yes I've checked the file's names and they are the same.
Just in case I'm including my linker script on account of it being short and that I wrote it myself (first time) and I'm learning how to write them.
MEMORY
{
rom : ORIGIN = 0x00000000, LENGTH = 8K
ram : ORIGIN = 0x20004000, LENGTH = 16K
stack : ORIGIN = 0x20003FFF, LENGTH = 16K
}
SECTIONS
{
.nvic_vector : { } >rom /*The vector table that is initialized in c code*/
.text :
{
*(.text)
/*_DATAI_BEGIN = .;*/
} >rom
.data :
{
_DATA_LOAD = LOADADDR(.data); /*The absolute address of the data section*/
_DATA_BEGIN = .; /*From where to begin the copy to RAM*/
*(.data)
. = ALIGN(4); /*Make sure the byte boundary is correctly aligned*/
_DATA_END = .; /*Where to end the copy to RAM*/
} >ram AT >rom
.bss :
{
_BSS_BEGIN = .; /* Zero-filled run time allocate data memory */
*(.bss)
_BSS_END = .;
} > ram
.heap :
{
_HEAP = .;
} > ram
.stack :
{
. += LENGTH(stack);
. = ALIGN(4);
_STACKTOP = .; /* The top of the stack is the last available section of memory*/
} >stack
}
Any help would be appreciated.
You could separate compilation and linking, then it's easier to see
flags common both for compiler and linker
flags only for one of these
If you have main.c and startup.c, compilation should look like this:
arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -mfloat-abi=soft -Os -std=gnu99 -o startup.o -c startup.c
arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -mfloat-abi=soft -Os -std=gnu99 -o main.o -c main.c
As for linking
arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -mfloat-abi=soft -nostartfiles -T rom.ld -o main.elf startup.o main.o -lc -lm
If you want it in a single line:
arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -mfloat-abi=soft -Os -std=gnu99 -nostartfiles -T rom.ld -o main.elf startup.c main.c
So the main problem was this line:
arm-none-eabi-gcc bubblesort.c -O0 -mcpu=cortex-m0 -mthumb -Wl, -T ../boot_and_link/linker.ld -l ../boot_and_link/startup.o
This was wrong as the -l switched is used to link with a library and not to just point another object file which was my intention. You need to specify all files for linking as normal ordinary arguments to the linker. The way I ended up doing this was simply (taking Beryllium's advice) separating the compilation and linking into two steps and using two separate calls. Here are the commands that are run by my makefile:
<-------------------- Compiling C Source Files -------------------->
arm-none-eabi-gcc -O0 -c -mcpu=cortex-m0 -mthumb -g bubblesort.c -o bubblesort.o
<-------------------- Linking files -------------------->
arm-none-eabi-ld bubblesort.o ../boot_and_link/startup.o -nostartfiles -T ../boot_and_link/linker.ld -o bubblesort.elf
This worked.
PD: The first error (wher it says it cannot find : No such file or directory) had to to with incorrect spacing in the gcc call. However as I changed it, I cannot exactly recall where it was.
on my cortex-m3, i am trying to output a float variable to my UART port.. so i need to convert the float DATA into a char outputstr[].
For this purpose, i used sprintf from the libc.a
if i comment out the sprintf(), i can compile and link.
if i use sprintf(outputstr, "t"), i can compile and link.
if i use sprintf(outputstr, "The value is %f", DATA), i will get linking errors like: no memory region specified for loadable section `.rodata', '.bss', '.text', '.data'
But i had already added *(.rodata), *(.bss) etc... in my linker script as below:
...
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(reset_handler)
MEMORY {
ROM : ORIGIN = 0x08000000, LENGTH = 128K
RAM : ORIGIN = 0x20000000, LENGTH = 16K
}
SECTIONS {
.ROMdata 0x8000000: AT(0x8000000){
startup.o(.romvect)
. = ALIGN(0x4);
system_stm32l1xx.o(.rodata*)
*(.rodata*)
_ROMdataend_ = ALIGN(0x4);
}
.ROMstartup (_ROMdataend_): AT(_ROMdataend_){
startup.o(.startup)
lowlevelinit.o(.lowlevelinit .tempexchandler)
system_stm32l1xx.o(.text*)
. = ALIGN(0x4);
}
.RAMbss 0x20000000 (NOLOAD):{
lowlevelinit.o(.ramvectortable)
. = ALIGN(0x4);
_RAMbssstart_ = .;
startup.o(.stack .heap)
. = ALIGN(0x4);
sensor_MTH01.o(.bss*)
. = ALIGN(0x4);
comm_BT-HC-05.o(.bss)
tim6.o(.bss)
main.o(.bss)
system_stm32l1xx.o(.bss*)
*(.bss*)
_RAMbssend_ = ALIGN(0x4);
}
.RAMcode (_RAMbssend_): AT(LOADADDR(.ROMstartup)+SIZEOF(.ROMstartup)){
_RAMcodeVMAstart_ = .;
_RAMcodeLMAstart_ = LOADADDR(.RAMcode);
main.o(.ramcode .text)
tim6.o(.tim6isr)
tim6.o(.text)
sensor_MTH01.o(.text)
comm_BT-HC-05.o(.text)
exti0_isr.o(.exti0isr)
*(.text*)
KEEP (*(.eh_*))
_RAMcodeVMAend_ = ALIGN(0x4);
}
.RAMdata (_RAMcodeVMAend_): AT(LOADADDR(.RAMcode)+SIZEOF(.RAMcode)){
_RAMcodeLMAend_ = (LOADADDR(.RAMcode)+SIZEOF(.RAMcode));
_RAMdataVMAstart_ = .;
_RAMdataLMAstart_ = LOADADDR(.RAMdata);
sensor_MTH01.o(.data)
system_stm32l1xx.o(.data*)
*(.data*)
_RAMdataVMAend_ = ALIGN(0x4);
_RAMdataLMAend_ = LOADADDR(.RAMdata) + SIZEOF(.RAMdata);
}
}
...
Also, i did include the lib paths and include paths in my makefile as below:
On a side note, i am also using strlen() and other float division operations from the libc.a and libgcc.a and these functions complile, link and work ok.
...
CC = arm-none-eabi-gcc
AS = arm-none-eabi-as
LD = arm-none-eabi-ld
OBJCPY = arm-none-eabi-objcopy
CCFLAGS = -c -mcpu=cortex-m3 -mthumb -O0 -g -Wall
ASMFLAGS = -mcpu=cortex-m3 -mthumb --gdwarf-2
LDFLAGS = -T CortexM3.ld -M=memmap.map
OBJCPYFLAGS = -O ihex
FLOATFLAGS = -mfloat-abi=soft -mfpu=vfp
LIBDIR = -L C:\\yagarto-20121222\\lib\\gcc\\arm-none-eabi\\4.7.2\\thumb\\v7m -L C:\\yagarto-20121222\\arm-none-eabi\\lib\\thumb\\v7m
INCDIR = -I C:\\yagarto-20121222\\lib\\gcc\\arm-none-eabi\\4.7.2\\include -I C:\\yagarto-20121222\\arm-none-eabi\\include
all: m3.elf
m3.elf: startup.o lowlevelinit.o system_stm32l1xx.o main.o tim6.o exti0_isr.o sensor_MTH01.o comm_BT-HC-05.o
$(LD) $(LDFLAGS) $(LIBDIR) $^ -lc -lgcc -o $#
$(OBJCPY) $(OBJCPYFLAGS) m3.elf m3.hex
startup.o: startup.s
lowlevelinit.o: lowlevelinit.c system_stm32l1xx.h stm32l1xx.h core_cm3.h
system_stm32l1xx.o: system_stm32l1xx.c stm32l1xx.h core_cm3.h system_stm32l1xx.h
main.o: main.c stm32l1xx.h
tim6.o: tim6.c
exti0_isr.o: exti0_isr.c
sensor_MTH01.o: sensor_MTH01.c
comm_BT-HC-05.o: comm_BT-HC-05.c
clean:
-rm -f startup.o lowlevelinit.o system_stm32l1xx.o main.o tim6.o tim6_isr.o exti0_isr.o sensor_MTH01.o comm_BT-HC-05.o memmap.map m3.elf m3.hex
%.o: %.s
$(AS) $(ASMFLAGS) $< -o $#
%.o: %.c
$(CC) $(CCFLAGS) $(INCDIR) $(FLOATFLAGS) $< -o $#
.PHONY: all clean
...
can anyone advise?
also, if i come across linking error message like: no memory region specified for loadable section `.rodata'... how can i know which object's (.o) .rodata section is being left out of my linker script?
update:
i realized that if the sprintf() function is called in main(), the program can compile and link successfully.. but if i call the sprintf() function in other functions, i will get above linking errors (no memory region specified for loadable section .bss), even if i used *(.bss) as the input sections for my output sections.
To solve the linking errors ('no memory region specified for loadable section .bss etc', i had to add *(COMMON) in the BSS output section.