bad_coffee bad_coffee - 1 year ago 138
C Question

CLion, CMSIS and error: "expected identifier or '(' before '__asm'"

I'm trying to setup a CLion C working environment for my Cortex-M0 embedded processor. I'm completely new to CLion and cmake and I have been struggling for days with this problem:

The issue arises in the core_cm0.h header file included in CMSIS. More specifically at these lines:

#if defined ( __CC_ARM )
#define __ASM __asm /*!< asm keyword for ARM Compiler */
#define __INLINE __inline /*!< inline keyword for ARM Compiler */
#define __STATIC_INLINE static __inline

My project is as small as it gets with just a main() routine with a while(true) loop. When I try to build I get the error "expected identifier or '(' before '__asm'". I also get a bunch of similar notes and warnings like e.g. "warning: implicit declaration of function '__nop'". What is confusing me the most is that the same project compiles fine in Keil (the IDE I usually work in). So I figure it might be some compiler specific thing. Or is it something special with how the GNU toolchain handles inline assembly?

This is my CMakeLists.txt :

cmake_minimum_required(VERSION 3.6)
project(Test3 C ASM)

CMAKE_FORCE_C_COMPILER("C:/Program Files (x86)/GNU Tools ARM Embedded/5.4 2016q2/bin/arm-none-eabi-gcc.exe" GNU)


set(SOURCE_FILES main.c)


add_executable(Test3 ${SOURCE_FILES})

SET(COMMON_FLAGS "-mcpu=cortex-m0 -mthumb -mabi=aapcs --std=gnu99 -Werror -O0 -g3 -mfloat-abi=soft -ffunction-sections -fdata-sections -fno-strict-aliasing -fno-builtin --short-enums ")
SET(CMAKE_ASM_FLAGS "${COMMON_FLAGS} ${CMAKE_C_FLAGS} -x assembler-with-cpp")
SET(LINKER_SCRIPT ${CMAKE_SOURCE_DIR}/default_linker_nrf51.ld)
SET(CMAKE_EXE_LINKER_FLAGS "-mcpu=cortex-m0 -Wl,-gc-sections -T --specs=nano.specs -lc -lnosys -mthumb -mabi=aapcs -L ${LINKER_SCRIPT} -Xlinker -Map=${LISTING_DIRECTORY}/${OUTPUT_FILENAME}.map")

And this is my toolchain setup in CLion:

Answer Source

Note that the problematic definitions are protected by #if defined ( __CC_ARM ).

__CC_ARM is an internal symbol defined by the ARM Compiler (which is the one Keil provides), so having it manually defined in your add_definitions leads to the code using a bunch of armcc-specific syntax and builtins which GCC doesn't understand.

More generally, the C standard says that identifiers beginning with double-underscores are reserved for the implementation (i.e. compiler), so if do you find yourself manually defining them it's a sign that you're probably doing something wrong.