Кросс компиляция под микроконтроллеры AVR при помощи CMake

CMake очень мощная система сборки. Она давно известна разработчикам настольных приложений. Её используют такие проекты как OpenCV, KDE. В этой статье рассмотрим, как при помощи CMake собирать проекты под микроконтроллеры AVR. Я пробовал собирать проекты для AVR из под AVRStudio и Eclipse. AVRStudio мне не понравилась как среда разработки. А у Eclipse мне не понравился файл проекта. Я в нём так и не смог сделать некоторые вещи, которые в CMake делаются одной строчкой.

 
Объясню, как работать с CMake, на примере простого проекта.

Сначала создадим файл для кросс компиляции под AVR navigation_crosscompile.cmake.
Выбираем компиляцию под контроллер без операционной системы.

SET(CMAKE_SYSTEM_NAME Generic)

В качестве компилятора выбираем avr-gcc для кода на C и avr-g++ для кода на C++.

SET(CMAKE_C_COMPILER avr-gcc)
SET(CMAKE_CXX_COMPILER avr-g++)

Настраиваем компилятор так же как это делает AVR Studio.

SET(CSTANDARD "-std=gnu99")
SET(CDEBUG "-gstabs")
SET(CWARN "-Wall -Wstrict-prototypes")
SET(CTUNING "-funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums")

Выбираем тип оптимизации. В данном случае выбрана оптимизация размера кода(Os).

SET(COPT "-Os")

Указываем модель микроконтроллера.

SET(CMCU "-mmcu=atmega32")

Указываем тактовую частоту, на которой работает микроконтроллер.

SET(CDEFS "-DF_CPU=12000000UL")

Передаём все установленные параметры компиляторам.

SET(CFLAGS "${CMCU} ${CDEBUG} ${CDEFS} ${CINCS} ${COPT} ${CWARN} ${CSTANDARD} ${CEXTRA}")
SET(CXXFLAGS "${CMCU} ${CDEFS} ${CINCS} ${COPT}")
SET(CMAKE_C_FLAGS  ${CFLAGS})
SET(CMAKE_CXX_FLAGS ${CXXFLAGS})

Теперь напишем Makefile для сборки статической библиотеки для работы с LCD дисплеем.
Указываем минимальную необходимую версию CMake.

CMAKE_MINIMUM_REQUIRED(VERSION 2.6.0)

Включаем файл для кросс компиляции.

INCLUDE(${NAVIGATION_BASE_DIRECTORY}/navigation_crosscompile.cmake)

Указываем название библиотеки.

PROJECT(LCD)
MESSAGE(STATUS "\nCreating LCD library...")

Указываем заголовочные файлы и файлы с исходным кодом, которые нужно собрать в виде статической библиотеки.

SET(HEADER_FILES
        defines.h
        hd44780.h
        lcd.h)
SET(SOURCE_FILES 
        hd44780.c
        lcd.c)
ADD_LIBRARY(LCD ${HEADER_FILES} ${SOURCE_FILES})

Делаем библиотеку видимой на всех уровнях проекта(в других библиотеках данного проекта, в исполняемом файле).

SET(LCD_LIBRARY LCD CACHE PATH "LCD library valiavle")

Создадим Makefile для сборки исполняемого файла, который будет линковать нашу библиотеку. В этом файле всё аналогично файлу для сборки библиотеки.

CMAKE_MINIMUM_REQUIRED(VERSION 2.6.0)
 
INCLUDE(${NAVIGATION_BASE_DIRECTORY}/navigation_crosscompile.cmake)
 
PROJECT(master)
 
MESSAGE(STATUS "\nCreating master project...")
 
SET(MAIN_FILE
        main.c)
 
ADD_EXECUTABLE(master ${MAIN_FILE})

Указываем, что наш исполняемый файл зависит от статической библиотеки.

ADD_DEPENDENCIES(master ${LCD_LIBRARY})
TARGET_LINK_LIBRARIES(master ${LCD_LIBRARY})

Последнее, что нужно сделать, - это написать файл, который запускает сборку статической библиотеки, а затем исполняемого файла.

CMAKE_MINIMUM_REQUIRED(VERSION 2.6.0)
 
INCLUDE(navigation_crosscompile.cmake)

Имя всего проекта.

PROJECT(navigation)
 
SET(NAVIGATION_BASE_DIRECTORY ${PROJECT_SOURCE_DIR})
INCLUDE_DIRECTORIES(${NAVIGATION_BASE_DIRECTORY})
 
# external libraries
SET(LCD_PATH ${NAVIGATION_BASE_DIRECTORY}/LCD)
INCLUDE_DIRECTORIES(${LCD_PATH})
ADD_SUBDIRECTORY(${LCD_PATH})
 
# executables
ADD_SUBDIRECTORY(${NAVIGATION_BASE_DIRECTORY}/master)

Чтобы скомпилировать проект, нужно выполнить следующую последовательность действий:
1) Зайти в корневую папку проекта из консоли

2)	mkdir build
3)	cd build

4) При работе в ОС Linux:

 cmake ..

При работе в ОС Windows:

 cmake –G”MinGW Makefiles” ..
5)	make

При исполнении команды cmake –G”MinGW Makefiles” .. под Windows у меня возникают странные ошибки вида:
CMake Error at C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/CMakeMinGWFindMake.cmake:20 (MESSAGE):
sh.exe was found in your PATH, here:
C:/WinAVR-20100110/utils/bin/sh.exe
For MinGW make to work correctly sh.exe must NOT be in your path.
Run cmake from a shell that does not have sh.exe in your PATH.
If you want to use a UNIX shell, then use MSYS Makefiles.
Call Stack (most recent call first):
CMakeLists.txt:11 (PROJECT)
CMake Error: Error required internal CMake variable not set, cmake may be not be built correctly.
Missing variable is:
CMAKE_C_COMPILER_ENV_VAR
CMake Error: Could not find cmake module file:C:/Users/Dmitry/Desktop/navigation/build/CMakeFiles/CMakeCCompiler.cmake
CMake Error: Error required internal CMake variable not set, cmake may be not be built correctly.
Missing variable is:
CMAKE_CXX_COMPILER_ENV_VAR
CMake Error: Could not find cmake module file:C:/Users/Dmitry/Desktop/navigation/build/CMakeFiles/CMakeCXXCompiler.cmake
-- Configuring incomplete, errors occurred!

Но если выполнить её ещё раз, они пропадают.
Если вы не любите консоль всё это можно проделать из QtCreator в графическом режиме. Он отлично работает с CMakeList.txt(файлы сборки для CMake).
В результате компиляции получается файл .elf, хотя он и не имеет этого расширения. Чтобы конвертировать его в файл .hex для заливки на МК:
(в cmake можно набросать простенький макрос)

# create avr hex
MACRO(AVR_CREATE_HEX name)
 
ADD_CUSTOM_COMMAND(TARGET ${name} POST_BUILD COMMAND avr-objcopy ARGS -O ihex -R.eeprom ${name} ${HEX_PATH}/${name}.hex)
 
ENDMACRO(AVR_CREATE_HEX)

(из shell)

cd build
avr-objcopy -O ihex -R.eeprom master/master master/master.hex

Чтобы компилировать проекты при помощи CMake под Windows необходимо поставить CMake, WinAVR. Пути к WinAVR должны быть прописаны в переменной окружения Path.
Я вместо Windows предпочитаю openSUSE. Там необходимо поставить avr-gcc, всё остальное стоит стандартно.

Скачать пример.

Leave a Reply

You must be logged in to post a comment.