When building from STM32CubeIDE, all good (obviously)
When building outside IDE, but using exactly the same toolchain (ST's) and the same compiler & link flags, I got some HardwareFault handler :((
So basically, some flags/specs are not good on my side.
Now after investigating a little (-verbose) I noticed there is a difference in IDE's toolchain libraries compared to mine (both at compile & link files)
This is a link example log
IDE's
c:\st\stm32cubeide_1.11.0\stm32cubeide\plugins\com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.10.3-2021.10.win32_1.0.100.202210260954\tools\arm-none-eabi\bin\ld.exe: mode armelf
attempt to open c:/st/stm32cubeide_1.11.0/stm32cubeide/plugins/com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.10.3-2021.10.win32_1.0.100.202210260954/tools/bin/../lib/gcc/arm-none-eabi/10.3.1/thumb/v6-m/nofp/crti.o succeeded
It is choosing
../lib/gcc/arm-none-eabi/10.3.1/thumb/v6-m/nofp/crti.o
Mine
c:\st\stm32cubeide_1.11.0\stm32cubeide\plugins\com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.10.3-2021.10.win32_1.0.100.202210260954\tools\arm-none-eabi\bin\ld.exe: mode armelf
attempt to open c:/st/stm32cubeide_1.11.0/stm32cubeide/plugins/com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm3
2.10.3-2021.10.win32_1.0.100.202210260954/tools/bin/../lib/gcc/arm-none-eabi/10.3.1/thumb/nofp/crti.o succeeded
And mine is choosing
thumb/nofp/crti.o
For some reason, at my side appears that NANO is not choosen.
Moreover, libgcc is choosen in the first place!
This is mine
./Drivers/STM32G0xx_HAL_Driver/Src/stm32g0xx_ll_rcc.o
attempt to open ../../../test1\libgcc.a failed
attempt to open c:/st/stm32cubeide_1.11.0/stm32cubeide/plugins/com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm3
2.10.3-2021.10.win32_1.0.100.202210260954/tools/bin/../lib/gcc/arm-none-eabi/10.3.1/thumb/nofp\libgcc.a succeeded
This is IDE's
./Drivers/STM32G0xx_HAL_Driver/Src/stm32g0xx_ll_rcc.o
attempt to open c:/st/stm32cubeide_1.11.0/stm32cubeide/plugins/com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.10.3-2021.10.win32_1.0.100.202210260954/tools/bin/../lib/gcc/arm-none-eabi/10.3.1/thumb/v6-m/nofp\libc_nano.a failed
attempt to open c:/st/stm32cubeide_1.11.0/stm32cubeide/plugins/com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.10.3-2021.10.win32_1.0.100.202210260954/tools/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/lib/thumb/v6-m/nofp\libc_nano.a succeeded
These are my link flags
`-O0`,
`-Wl,-verbose`,
`--specs=nosys.specs`,
`--specs=nano.specs`,
`-static`,
`-Xlinker --gc-sections`,
`-Xlinker --print-memory-usage`,
`-mfloat-abi=soft`,
`-mthumb`,
And these are IDE's
-mcpu=cortex-m0plus -T"STM32G0B1RETX_FLASH.ld" --specs=nosys.specs -Wl,-Map="${BuildArtifactFileBaseName}.map" -Wl,--gc-sections -Wl,--verbose -static --specs=nano.specs -mfloat-abi=soft -mthumb -Wl,--start-group -lc -lm -Wl,--end-group
What can be wrong?
Thanks in advace,
I would have hoped this was obvious, but you need -mcpu=cortex-m0plus (or -march=armv6-m).
Sorry to put as answer, thanks #Tom V for clue, you're the man :)
I just silly forgot to specify -mcpu=cortex-m0plus to my linker too!
And yes, I prefer VS Code as IDE and build externally with my own scripts. Just tired of ST's hidden params & updates that crashes old projects.
But I still have to use STM32Cube for debug on-target purposes, step into running code, view registers & peripheral definitions, etc.
Related
I'm trying to compile C code for GCC, but the linker is unable to find libgcc.
I want to compile some simple tests for an RV32I core.
When I try to use the modulo operator, GCC generates a call to the soft implementation of
the mod instruction.
call __modsi3
But linking fails because I think im missing libgcc
test.c:(.text+0x34): undefined reference to `__modsi3'
This is my compilation command:
riscv64-unknown-elf-gcc -lm -lgcc -static -march=rv32i -mabi=ilp32 -nostartfiles -ffreestanding crt0.s -O0
These are my linker options:
-lgcc -b elf32-littleriscv -m elf32lriscv
If I try to use the -lgcc option on the linker, it will throw the following error:
riscv64-unknown-elf-ld: cannot find -lgcc
I also tried to provide directly the path of libgcc.a. But it didn't help.
I got the path of libgcc.a this way:
riscv64-unknown-elf-gcc -march=rv32i -print-libgcc-file-name
I added the path directly to my compilation command like so:
-L="/mnt/c/Users/camin/Documents/opt/riscv/lib/gcc/riscv64-unknown-elf/10.2.0/libgcc.a"
Also, the way I compiled the toolchain might be the issue, I'm using the RISCV toolchain with multi-lib support
I followed the instructions from https://github.com/riscv/riscv-gnu-toolchain
with some slight modification (-j12)
./configure --prefix=/opt/riscv --enable-multilib
make -j12
This also installed the toolchain so I didn't had to make install
Thanks.
The problem comes from -L="/mnt/c/Users/camin/Documents/opt/riscv/lib/gcc/riscv64-unknown-elf/10.2.0/libgcc.a" you must only give the path to the L option. Your option should be :-L="/mnt/c/Users/camin/Documents/opt/riscv/lib/gcc/riscv64-unknown-elf/10.2.0"
the enable-multilib is working well, it only provide libraries for set of archs. However be careful to give the path of the libgcc corresponding to your arch. When you enable multilib the default one will be a 64 bit versions. Normally for rv32i, the option you need is :-L="/mnt/c/Users/camin/Documents/opt/riscv/lib/gcc/riscv64-unknown-elf/10.2.0/rv32i/ilp32".
If you don't give the good library you will probably get ABI is incompatible with that of the selected emulation error.
It would be easier to use the riscv64-unknown-elf-gcc driver to make the link because he knows all the options better. Normally it will find the necessary libraries (libgcc, libgloss ....) automatically for your arch.
This worked for me, had to manually add the path to the libgcc.a as an argument to elf-ld:
riscv32-unknown-elf-ld -o exampleProg2.elf -T bram.ld -m elf32lriscv -nostdlib --no-relax /(RVTOOLCHAIN_GCC_LIB_DIR)/libgcc.a
Just be careful of choosing the right libgcc.a, there may be multiple in your installation, depending of your multilib seutp.
I now work on C code coverage study and encountered following issue, GCC version 4.4.6:
Added compiler flag CFLAGS = --coverage and linker option LDFLAGS := --coverage or LOCAL_LDLIBS := --coverage and got the error:
undefined reference to '__gcov_init'" and "undefined reference to '__gcov_merge_add'
Added option LOCAL_LDFLAGS := --coverage, and got link error:
libgcov.a(_gcov.o): in function __gcov_set_sampling_rate: undefined reference to '__gcov_sampling_rate'
libgcov.a(_gcov.o): in function gcov_exit: undefined reference to '__gcov_pmu_profile_filename'
libgcov.a(_gcov.o): in function __gcov_init: undefined reference to '__gcov_pmu_profile_options' '__gcov_pmu_top_n_address'
Can anyone help to provide some suggestions on this issue?
Try this approach:
Compile the code for which you want to generate the coverage with these options:
CFLAGS: -fprofile-arcs -ftest-coverage
LFLAGS: -lgcov --coverage
If this doesn't solve the problem, then please provide some information on the structure of your application, i.e. whether its single program or an application involving shared/static libraries etc.
Are you linking with -lgcov?
If you are using a Makefile it would be of great help to have a look at it in order to help you.
you have to provide LDFLAGS to resolve this issue.
LDFLAGS += " -lgcov --coverage"
I can't be sure which change finally did the trick for me but I think it was the -fprofile-generate flag. Using GNAT GPS I went to the Switches tab on the left and then selected the Ada Linker tab on the top. Then I enabled the checkbox for Code Coverage. Oh yeah I've found that on the Builder tab in that same area if you enable the Recompile if switches changed checkbox it can save a lot of teeth-gnashing. Probably slows things down for the pros but I found it helpful.
I found I had to put the '-lgcov' to the right of the object being profiled instead of in Flags. Something like.
gcc -pg -o myprog myprog.o -lgmp.a -lgcov
I had undefined reference to gcov functions (undefined reference to '__gcov_exit') while I tried to enable coverage on a C project using a C++ test harness (CppUTest). Build system was handled by CMake.
Compilers and gcov were aligned on the same version (gcc --version, g++ --version and gcov --version gave the same version) but it seems that my build system was previously configured to use gcc 5 while g++ 8 and gcov 8 were used (resulting to an additional included directory by the linker: usr/lib/gcc/x86_64-linux-gnu/5). I cleaned the build tree and generated it again thanks to CMake which fixed the error.
I have seen this issue too and as most of the answers above indicated it needed us to add lcov/gcov libraries at the time of linking.
We are using cmake and in CmakeLists.txt file we were missing
target_link_libraries(${TARGET_NAME} PRIVATE gcov)
This was needed of course in addition to the build flag "--coverage"
(Pls note we can either use "--coverage" or "-fprofile-arcs -ftest-coverage" separately)
I am having extreme trouble cross compiling a project related to gstreamer. I am trying to link it to a library on my cross compile machine's /usr/lib
If I do the standard linker flags -L{FILESYS_DIR}/usr/lib -lGLESv2 I get pthread complaints from my cross compile toolchain. Thus, I am trying to link to this library without using the -L flag.
No matter what I do, I am getting undefined symbol glFramebuffer2D. However a quick readelf -Wc $FILESYS_DIR/usr/lib/libGLESv2.so | glFrame shows me a glFramebuffer2D symbol.
I'm pulling my hair out because no matter what flags I specify to autoconf, something called libtool throws away my link request unless I use the -L -l approach...
Edit: I had another idea, I tried -Wl, $FILESYS_DIR/usr/lib/libGLESv2.so which worked in compiling and linking but not during runtime... Obvious to me (now) because the host machine root is $FILESYS_DIR. Anyways, this is on the right approach, but I guess I need relative names.
libtool: link: arm-none-linux-gnueabi-gcc -shared .libs/libgstbla_la-gstblaoverlay.o
.libs/libgstbla_la-gstblastabilize.o .libs/libgstbla_la-gles2_utilities.o -Wl,-
rpath -Wl,/home/z3/z3-netra/filesys/fs//opt/gstreamer-0.4/lib -Wl,-rpath -
Wl,/home/z3/z3-netra/filesys/fs//opt/gstreamer-0.4/lib -L/home/z3/z3-
netra/filesys/fs/opt/gstreamer/lib /home/z3/z3-netra/filesys/fs//opt/gstreamer-
0.4/lib/libgstbase-0.10.so /home/z3/z3-netra/filesys/fs//opt/gstreamer-
0.4/lib/libgstreamer-0.10.so /home/z3/z3-netra/filesys/fs//opt/gstreamer-
0.4/lib/libgstvideo-0.10.so /home/z3/z3-netra/filesys/fs//opt/gstreamer-
0.4/lib/libgobject-2.0.so /home/z3/z3-netra/filesys/fs//opt/gstreamer-
0.4/lib/libgmodule-2.0.so /home/z3/z3-netra/filesys/fs//opt/gstreamer-
0.4/lib/libgthread-2.0.so -lrt /home/z3/z3-netra/filesys/fs//opt/gstreamer-
0.4/lib/libglib-2.0.so -pthread -Wl,-soname -Wl,libgstbla.so -Wl,-version-script -
Wl,.libs/libgstbla.ver -o .libs/libgstbla.so
If needed, in one line as well:
libtool: link: arm-none-linux-gnueabi-gcc -shared .libs/libgstbla_la-gstblaoverlay.o .libs/libgstbla_la-gstblastabilize.o .libs/libgstbla_la-gles2_utilities.o -Wl,-rpath -Wl,/home/z3/z3-netra/filesys/fs//opt/gstreamer-0.4/lib -Wl,-rpath -Wl,/home/z3/z3-netra/filesys/fs//opt/gstreamer-0.4/lib -L/home/z3/z3-netra/filesys/fs/opt/gstreamer/lib /home/z3/z3-netra/filesys/fs//opt/gstreamer-0.4/lib/libgstbase-0.10.so /home/z3/z3-netra/filesys/fs//opt/gstreamer-0.4/lib/libgstreamer-0.10.so /home/z3/z3-netra/filesys/fs//opt/gstreamer-0.4/lib/libgstvideo-0.10.so /home/z3/z3-netra/filesys/fs//opt/gstreamer-0.4/lib/libgobject-2.0.so /home/z3/z3-netra/filesys/fs//opt/gstreamer-0.4/lib/libgmodule-2.0.so /home/z3/z3-netra/filesys/fs//opt/gstreamer-0.4/lib/libgthread-2.0.so -lrt /home/z3/z3-netra/filesys/fs//opt/gstreamer-0.4/lib/libglib-2.0.so -pthread -Wl,-soname -Wl,libgstbla.so -Wl,-version-script -Wl,.libs/libgstbla.ver -o .libs/libgstbla.so
/usr/lib should already be on the library search path, so you shouldn't need to specify an RPATH. What you do need to do though, is to tell your (cross-)linker where to find the libraries. I think that includes transitively dependencies, such as libpthread. Do you have $FILESYS_DIR/usr/lib/libpthread.so? Does it point to /lib/libpthread.so.N? Oh wait, I see something now that I wrote it out: notice the (likely) absence of $FILESYS_DIR there: so it's possible that your linker is looking for libpthread transitively needed by libGLESv2, but not finding it, since $FILESYS_DIR/lib is not on the library include path. Add -L $FILESYS_DIR/lib to your linker flags and try again.
All, this was related to the following question: set global gcc default search paths
The problem here is related to the pthread.so (also glib.so). /usr/lib/pthread.so on a lot of systems is an ASCII script which then further links to the system's /lib/pthread.so.0 (which is a soft link). When compiling, my $(FILESYS_DIR) was correct, however the the libpthread.so there pointed to the host systems pthread.so
I made a HUGE mistake here which could have been easily avoided with correct cross compilation management. When compiling for a target system, do not use files on the target system filesystem (if it's a NFS as mine was.) Use local libraries compiled for that target system. FURTHERMORE, specify -Wl,-rpath-link=/[local location where your *.so reside]
That compiler/linker flag allows for the runtime path to be on the local system during compile and link, but maintain the standard runtime path during runtime.... Hope that made sense.
compilation options for cmake (on windows) for ARM target system but when I run configure it's starting compiler tests:
CMake Error at D:/Program Files/CMake 2.8/share/cmake-2.8/Modules/CMakeTestCCompiler.cmake:52 (MESSAGE):
The C compiler "D:/Program Files/yagarto/bin/arm-none-eabi-gcc.exe" is not
able to compile a simple test program.
It fails with the following output:
Change Dir: D:/merge/complex/build/CMakeFiles/CMakeTmp
Run Build Command:D:/PROGRA~1/YAGART~1/bin/make.exe "cmTryCompileExec/fast"
D:/PROGRA~1/YAGART~1/bin/make.exe -f
CMakeFiles/cmTryCompileExec.dir/build.make
CMakeFiles/cmTryCompileExec.dir/build
make.exe[1]: Entering directory
`D:/merge/complex/build/CMakeFiles/CMakeTmp'
"D:/Program Files/CMake 2.8/bin/cmake.exe" -E cmake_progress_report
D:/merge/complex/build/CMakeFiles/CMakeTmp/CMakeFiles 1
Building C object CMakeFiles/cmTryCompileExec.dir/testCCompiler.c.o
"D:/Program Files/yagarto/bin/arm-none-eabi-gcc.exe" -o
CMakeFiles/cmTryCompileExec.dir/testCCompiler.c.o -c
D:/merge/complex/build/CMakeFiles/CMakeTmp/testCCompiler.c
Linking C executable cmTryCompileExec
"D:/Program Files/yagarto/bin/arm-none-eabi-gcc.exe"
"CMakeFiles/cmTryCompileExec.dir/testCCompiler.c.o" -o cmTryCompileExec
-rdynamic
arm-none-eabi-gcc.exe: error: unrecognized option '-rdynamic'
make.exe[1]: *** [cmTryCompileExec] Error 1
Using Yagatdo 4.6.* cross-compilation toolchain
How can I skip this tests or fix -rdynamic error that I am getting?
You can set CMAKE_<LANG>_COMPILER_WORKS to true to suppress further compiler checks for that language.
set(CMAKE_C_COMPILER_WORKS 1)
You can skip the compiler checks by adding NONE to your project call:
project(<projectname> NONE)
but this can have pretty far-reaching effects. For full details, run
cmake --help-command project
I'm not familiar with ARM, so this is probably not your best option here. I guess you'd be better to see if there's a way to fix the -rdynamic flag.
EDIT:
It looks like this was identified as a bug which is effectively still unresolved. The comments in the bug report mention adding the following lines as a workaround (presumably before your project call):
set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
It seems you target actually something else than Linux, so you should tell cmake that you are cross-compiling for the generic case:
SET(CMAKE_SYSTEM_NAME Generic)
Followed by (optionally, but nice to specify):
SET(CMAKE_SYSTEM_PROCESSOR arm)
SET(CMAKE_CROSSCOMPILING 1)
However, if you specify (which you likely did because this is stated in a lot of examples online):
SET(CMAKE_SYSTEM_NAME Linux)
Then cmake will load the configuration files from (suppose version 2.8) the file:
/usr/share/cmake-2.8/Modules/Platform/Linux.cmake
from which it is likely to load:
/usr/share/cmake-2.8/Modules/Platform/Linux-GNU.cmake
Here the -rdynamic flag is set for historical reasons:
macro(__linux_compiler_gnu lang)
# We pass this for historical reasons. Projects may have
# executables that use dlopen but do not set ENABLE_EXPORTS.
set(CMAKE_SHARED_LIBRARY_LINK_${lang}_FLAGS "-rdynamic")
endmacro()
Rather than disabling the tests as indeed is done by specifying NONE as the PROJECT argument, it seems setting the CMAKE_SYSTEM_NAME (to something else than Linux, for instance Generic) is what you actually want to do.
If you're just compiling a static library and you want to avoid having CMake test that the compiler can generate binaries, you can set the variable CMAKE_TRY_COMPILE_TARGET_TYPE.
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
When cross compiling for Windows, where there is no -rdynamic option, you can use
-DCMAKE_SYSTEM_NAME="Windows"
with cmake. Then Cmake will skip the test with -rdynamic.
I am having a problem with _sbrk. In a link phase of compilation i use below comand to link my objects and i get undefined reference to _sbrk.
arm-none-eabi-ld -static -T linkerscript.ld -o exe timer_example.o /home/ziga/projects/cs_lite/arm-none-eabi/lib/libc.a /home/ziga/projects/cs_lite/lib/gcc/arm-none-eabi/4.5.1/libgcc.a
I am compiling for arm926ej-s and in ARM mode so i think i have chosen the right multilib (libc.a and libgcc.a) which is located in folder home/ziga/projects/cs_lite/arm-none-eabi/lib/.
I have been searching internet for _sbrk function and it is some sort of a memory managment call which isnt included in standard C libraries as it is dependant on microprocessor. So do I have to write _sbrk function on my own? How do I do it? Do you have any example for arm926ej-s? After writing this function I intend to compile it into an object file and link it together with other objects, libraries.
This helps:
-mcpu=cortex-m4 -mthumb -specs=nano.specs -specs=nosys.specs -mfpu=fpv4-sp-d16 -mfloat-abi=hard
The important switches "seem" to be:
-specs=nano.specs -specs=nosys.specs
I was having the same problem, and adding those to the linker flags helped:
-specs=nano.specs -specs=nosys.specs
Also, just with the nosys.specs fixed the issue, but the code size was a lot bigger.
The problem has little to do with _sbrk itself, but rather your attempt to invoke the linker directly, bypassing the compiler driver. Instead, use the gcc command to invoke the linker and the -Wl,-linkeroptionhere syntax to pass extra options to the linker.
One possible solution, if you must invoke the linker yourself.. Try repeating both libc.a and libgcc.a a second time at the end of the command line. There's also some "as group" linker option you could use to achieve this but I don't know it right off.
recently I also ran into this(again). the easiest solution which worked for me was to provide/redirect "malloc" and "free" apis to the one available from the SDK on which I was building my application.
Basically it happens because of mem management apis missing while linking. like the above answer mentions its not that _sbrk is specifically missing here. brk/sbrk syscall intenrally is used for heap management. hence the _sbrk ,missing link when it comes to mem management apis.
I noticed that adding -lnosys (i.e libnosys.a) also helped a this to a degree in some integrations.
with visualgdb (using gcc), and nanolib, I had to add the linker flag
-specs=nosys.specs
I solved this problem and will post solution here so i give something back to comunity. The function _sbrk is located inside NXP CDL package for ARM. Package is available for download (link is for all who dont know this already) here in subfolder CDL_v005/csps/lpc313x/bsps/ea3131/source you will find source file named libnosys_gnu.c which should be added to the project and compiled to object file and after that linked to executable file alongside other objects and libraries.
Best wishes and a lot of success.