I debug STM32 project created with CMake. It uses HAL library and at the beginning I configure HAL and SysTick.
root/
├─ core/
│ ├─ core.c
│ ├─ core.h
│ ├─ stm32g4xx_it.c
│ ├─ stm32g4xx_it.h
│ ├─ CMakeLists
├─ main.c
├─ startup.s
├─ CMakeLists.txt
startup.s
file contains weak SysTick_Handler, as follows:
.weak SysTick_Handler
.thumb_set SysTick_Handler,Default_Handler
stm32g4xx_it.c
also contains SysTick_Handler
which overrides weak declaration.
The problem is when compile, link and load the app as it looks like above, SysTick interrupt ends in Default_Handler
. If I remove weak declaration from startup.s
file, then it works properly and correct handler function is executed. I think this is a result of how cmake works. In the root directory there's a main CMakeLists.txt file which compiles startup.s
and main.c
files, then links core library. The correct SysTick handler
is placed in the core library, thus compilation of startup.s
file "doesn't see" the other implementation of this handler function.
What is the correct yet elegant approach to solve it?
Another question which comes to my mind is how should I write code for other interrupt handlers and how to link them in CMake building system? Let's say I have a UART module and that module has its own interrupt handlers. Should I create a separate library which is based on startup.s
file and link all other modules which have interrupt handlers to it? I thought CMake should make building more transparent, readable and easy but that way it looks more like spaghetti. Probably I'm missing something...
EDIT 4/14/2021
I found out that the problem is only related to startup asm file. For example, I can create a weak function symbol in main.c, e.g.:
__attribute__((weak)) void SystemInit(void)
In the core library, in core.c I create function:
void SystemInit(void)
then after compilation and linking the correct function from core.c is used. So it looks like there's something strictly related to asm file here.
The reason for such linker behavior is the fact it treats libraries in different way. When it finds weak symbol in source files, it stops looking for the same symbols in libraries. The reason for that is libraries provides some functionalities and developers should be able to override these functionalities to align them with own projects.
There's no need to use libraries in embedded projects for microcontrollers. I found it causes more pain. Some developers doesn't use libraries add_library()
in their CMakeLists.txt
. I don't find it very reasonable while using CMake. It's used to better organize project files and manage dependencies between modules.
The problem here can be simply solved with use OBJECT
libraries. That type of link has been added to target_link_libraries
in the version of 3.12. I think it has been added for the microcontroller projects specifically and it really works excellent.