CMSIS2000  0.0.7
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
Using CMAKE for compiling projrect

Making new CMAKE project

A new CMAKE project is created by writing CMakeLists.txt file.

Adjusting a some project to specific micro-controller and board is made by running CMAKE utility with three commandline parameters.

  • MCU model
  • Board
  • Code linkage variant (FLASH, RAM, or EXTERNAL RAM)

CMAKE project examples

CMAKE project examples can be found at directories :

  • Device/NXP/LPC2xxx/templates/empty_main/cmake
  • Device/NXP/Drivers/Examples/UART/Interrupt/GCC_CMAKE
  • Device/NXP/Drivers/Examples/Project_Template/CMAKE_CMSIS2000/GCC_CMAKE

Let look CMAKE system running example at the command line –

cmake . -DCMAKE_TOOLCHAIN_FILE=../../../../../../../CMAKE/CMSIS.cmake -DCMAKE_BUILD_TYPE=Debug -DMCU=LPC1768 -DBSP_BRD_DEF=EA_v1_1 -DLINKAGE=FLASH -G "CodeBlocks - MinGW Makefiles"

The next line

-DCMAKE_TOOLCHAIN_FILE=../../../../../../../CMAKE/CMSIS.cmake

give CMAKE a compilation rules file for ARM

-DMCU=LPC1768

describe microcontroller model

-DBSP_BRD_DEF=EA_v1_1

sets the board name

-DLINKAGE=FLASH

sets that program must be located in the FLASH memory see Choosing CMAKE linkage

-G "CodeBlocks - MinGW Makefiles"

sets to CMAKE a project generation variant. May be some of them are suitable for you:

  • MinGW Makefiles = Generates a make file for use with mingw32-make.
  • Unix Makefiles = Generates standard UNIX makefiles.
  • CodeBlocks - MinGW Makefiles= Generates CodeBlocks project files.
  • CodeBlocks - Unix Makefiles = Generates CodeBlocks project files.
  • Eclipse CDT4 - MinGW Makefiles Generates Eclipse CDT 4.0 project files.
  • Eclipse CDT4 - Unix Makefiles = Generates Eclipse CDT 4.0 project files.

additional CMAKE options is set build type Release/Debug

-DCMAKE_BUILD_TYPE=Debug
-DCMAKE_BUILD_TYPE=Release

СMAKE settings

Choosing CMAKE linkage

The build variant is set by -DLINKAGE option. There is three build variants:

  • FLASH
  • RAM
  • ONE_SECT

FLASH – program image located in FLASH, program starts its execution from FLASH, data and some code section (.text.ram_code) is loaded to internal RAM.

RAM – program image located in FLASH, program starts its execution from FLASH, const data section (.rodata) and some code section (.text.rom_code) stay in FALSH, other code sections and data sections is loaded to internal RAM.

ONE_SECT – all program image is located in ONE SECTION, this section located in internal ram by default. But you can set the start and length of this section by using ONE_SEC_START and ONE_SEC_LENGTH variables. \сode -DLINKAGE=ONE_SECT -DONE_SEC_START=0xa0400000 -DONE_SEC_LENGTH=0x10000

Every build type gives its own linker script (FLASH.ld, ONE.ld, RAM.ld).

Other CMAKE options

MCU and Board (BSP_BRD_DEF) definition option.

An option

-DMCU=LPC1768

sets MCU model, makes mcu_id.h file with core type and MCU model definitions.

-DBSP_BRD_DEF=EA_v1_1

sets board, also tries to find in bsp floder a file this name EA_v1_1 and makes bsp_board_def.h file with string include "bps_board_EA_v1_1". Also add -D_HASBSPBRD=1 option to compiler.

Additional options to compiller COMMON_FLAGS

There is a way to make additional options to compiller. Next example shows how to set optimization option by size.

-DCMAKE_BUILD_TYPE=Debug -DCOMMON_FLAGS=-Os

Also there are options to each language COMMON_C_FLAGS, COMMON_CXX_FLAGS, COMMON_ASM_FLAGS , and COMMON_LD_FLAGS for linker.

Stack sizes in STARTAP_INIT_STACK_FILE_H

Stack pointer is sets to the end of SRAM memory. For more information see linker and runtime asm file.

STARTAP_INIT_STACK_FILE_H

STARTAP_INIT_STACK_FILE_H variable point to stack size settings file, by default startup_lpc_stack_generic.h.in is used.

-DAVOID_LINKER_SECTIONS=1

Remove -ffunction-sections -fdata-sections compilation options.

Main function run mode (only ARM7).

Main function run mode is a status register value then main() function executed. The main() function can be run in different modes (USER,SYSTEM,SWI).

STARTUP_ARM_MODE_MAIN

set status register value. By default it is MODE_SYS, but if there is TARGET_HAS_RTOS variable the value is set as (MODE_SVC|I_BIT|F_BIT). This masks interrupts before scheduler starts. TARGET_HAS_RTOS variable is set automaticli if there is "FreeRTOSConfig.h" or "iConfig.h" file in the root folder of project or one or two folder level higher.

CMAKE nano description.

CMAKE is a lisp-like language. Variables are set by SET command. case ARE not IMPORTANT

if(NOT DOXY_EXAMPLE_PATH)
set(DOXY_EXAMPLE_PATH ${DOXYGEN_INPUT_SOURCE_DIR})
endif(NOT DOXY_EXAMPLE_PATH)

Variable value is taken by curly braces like in Bash in opposite of parentheses like in Makefiles. Variables in CMAKE are represented like lists and can hold many elements.

As in Bash there is if() else() endif() supporting. Also there is functions and macroses.

Concatenation operations made in this manner :

set(prj_sources ${prj_sources} ${MB_SLAVE1_SRC})

CMakeLists.txt file.

CMakeLists.txt file for CMAKE can hold:

  • project name
  • list of source files
  • names of build targets and its dependences (libraries)
  • additional ``include'' commands with some CMAKE sources

There is CMakeLists.txt example in Device/NXP/LPC2xxx/templates/empty_main/cmake

There is CMakeLists.txt example in Device/NXP/Drivers/Examples/UART/Interrupt/GCC_CMAKE

## CMSIS2000
## CMSIS-like sources for LPC2xxx series MCUs
##
## This file is public domain you may use it as you wish
##
## Do not be lasy! For the latest version see http://irtos.sourceforge.net .
##
#set(STARTUP_ARM_MODE_MAIN "(MODE_SYS|I_BIT|F_BIT)")
project (uart_interrupt C ASM)
cmake_minimum_required(VERSION 2.8.4)
#add YOUR *.c and *.h files to you project here!!!!
set (exmpl_sources
../${CMAKE_PROJECT_NAME}_test.c
)
#There is directory with config files????
set(PROJECT_CONFIG_DIR "../")
include_directories(${PROJECT_CONFIG_DIR})
#for arch/interrupt and etc functions
include_directories("${CMSIS_ROOT_DIR}/2000/Include")
#Periphiral library
include(${CMSIS_ROOT_DIR}/Device/${MCU_VENDOR}/Drivers/CMAKE/periph_library.txt)
#Executables
add_executable(${CMAKE_PROJECT_NAME}.elf ${exmpl_sources})
#Libraries
target_link_libraries(${CMAKE_PROJECT_NAME}.elf
cmsis.crt0
${PERIPH_LIBRARY_NAME}
)
#Test CMAKE VARIABLES
include(${CMSIS_CMAKE_DIR}/test_system.cmake)
#CUSTOM FEATURES -- HEX BIN LST
add_custom_target(${CMAKE_PROJECT_NAME}.hex DEPENDS ${CMAKE_PROJECT_NAME}.elf COMMAND ${CMAKE_OBJCOPY} -Oihex ${CMAKE_PROJECT_NAME}.elf ${CMAKE_PROJECT_NAME}.hex)
add_custom_target(${CMAKE_PROJECT_NAME}.bin DEPENDS ${CMAKE_PROJECT_NAME}.elf COMMAND ${CMAKE_OBJCOPY} -Obinary ${CMAKE_PROJECT_NAME}.elf ${CMAKE_PROJECT_NAME}.bin)
add_custom_target(${CMAKE_PROJECT_NAME}.lst DEPENDS ${CMAKE_PROJECT_NAME}.elf COMMAND ${CMAKE_OBJDUMP} -D ${CMAKE_PROJECT_NAME}.elf > ${CMAKE_PROJECT_NAME}.lst)

CMAKE working internals

CMAKE system makes some temporary files (CMakeCache.txt, Makefile) and CMakeFiles directory in running directory. CMakeFiles directory is used for building and store all temporary results. Thus all trash files like *.obj, *.o, *.d and so on are NOT stored in main sources directories.

In the process of making project for CodeBlocks all libraries and executables are stored in list of targets automatically. It is a pity but there is no cross-compilation support for CodeBlock project files. That is why it is recommended to copy *.cbp file to *2.cbp and change project compiler from MinGW to ARM after that.

Some CMAKE features

  • make VERBOSE=1 – makes more verbose compiling output to console
  • make help – print the list of all targets among them libraries and hex file