Switch to nano version of newlib (#5180)
[opentx.git] / radio / src / CMakeLists.txt
blobb00a2781860c4277aaae0db98d02b724cdd717b2
1 include(CMakeForceCompiler)
2 include(Bitmaps)
4 set(PCB_TYPES X7 X7S X9D X9D+ X9E X10 X12S 9X 9XR 9X128 9XR128 9X2561 GRUVIN9X MEGA2560 SKY9X 9XRPRO AR9X)
5 set(GUI_LANGUAGES CZ DE EN ES FR IT PT SK SE PL HU NL)
6 set(TTS_LANGUAGES CZ DE EN ES FR IT PT SK SE PL HU)
8 set(PCB "X9D+" CACHE STRING "Radio type, one of: ${PCB_TYPES}")
9 set_property(CACHE PCB PROPERTY STRINGS ${PCB_TYPES})
10 set(TRANSLATIONS "EN" CACHE STRING "Radio language, one of: ${GUI_LANGUAGES}")
11 set_property(CACHE TRANSLATIONS PROPERTY STRINGS ${GUI_LANGUAGES})
12 set(SPLASH "DEFAULT" CACHE STRING "Splash (DEFAULT/OFF/FRSKY)")
13 set_property(CACHE SPLASH PROPERTY STRINGS DEFAULT OFF FRSKY)
14 set(PPM_UNIT "PERCENT_PREC1" CACHE STRING "PPM display unit (US/PERCENT_PREC1/PERCENT_PREC0)")
15 set_property(CACHE PPM_UNIT PROPERTY STRINGS US PERCENT_PREC1 PERCENT_PREC0)
16 set(DEFAULT_MODE "" CACHE STRING "Default sticks mode")
18 option(HELI "Heli menu" ON)
19 option(FLIGHT_MODES "Flight Modes" ON)
20 option(CURVES "Curves" ON)
21 option(GVARS "Global variables" OFF)
22 option(GUI "GUI enabled" ON)
23 option(PPM_CENTER_ADJUSTABLE "PPM center adjustable" ON)
24 option(PPM_LIMITS_SYMETRICAL "PPM limits symetrical" OFF)
25 option(OVERRIDE_CHANNEL_FUNCTION "OverrideChannel function available" ON)
26 option(DANGEROUS_MODULE_FUNCTIONS "Dangerous module functions (RangeCheck / Bind / Module OFF, etc.) available" OFF)
27 option(FAI "Competition mode (no telemetry)" OFF)
28 option(AUTOSOURCE "Automatic source detection in menus" ON)
29 option(AUTOSWITCH "Automatic switch detection in menus" ON)
30 option(SEMIHOSTING "Enable debugger semihosting" OFF)
31 option(JITTER_MEASURE "Enable ADC jitter measurement" OFF)
32 option(WATCHDOG_DISABLED "Disable hardware Watchdog" OFF)
33 if(SDL_FOUND)
34   option(SIMU_AUDIO "Enable simulator audio." ON)
35 endif()
36 option(SIMU_DISKIO "Enable disk IO simulation in simulator. Simulator will use FatFs module and simulated IO layer that  uses \"./sdcard.image\" file as image of SD card. This file must contain whole SD card from first to last sector" OFF)
37 option(SIMU_LUA_COMPILER "Pre-compile and save Lua scripts in simulator." ON)
38 option(FAS_PROTOTYPE "Support of old FAS prototypes (different resistors)" OFF)
39 option(TEMPLATES "Model templates menu" OFF)
40 option(TRACE_SIMPGMSPACE "Turn on traces in simpgmspace.cpp" ON)
41 option(TRACE_LUA_INTERNALS "Turn on traces for Lua internals" OFF)
42 option(BINDING_OPTIONS "Allow advanced frsky bindings" OFF)
43 option(FRSKY_STICKS "Reverse sticks for FrSky sticks" OFF)
44 option(NANO "Use nano newlib and binalloc")
46 # since we reset all default CMAKE compiler flags for firmware builds, provide an alternate way for user to specify additional flags.
47 set(FIRMWARE_C_FLAGS "" CACHE STRING "Additional flags for firmware target c compiler (note: all CMAKE_C_FLAGS[_*] are ignored for firmware/bootloader).")
48 set(FIRMWARE_C_FLAGS_DEBUG "-g" CACHE STRING "Additional flags for firmware target (Debug config) c compiler (note: CMAKE_C_FLAGS_DEBUG is ignored for firmware/bootloader).")
49 set(FIRMWARE_CXX_FLAGS "" CACHE STRING "Additional flags for firmware target c++ compiler (note: all CMAKE_CXX_FLAGS[_*] are ignored for firmware/bootloader).")
50 set(FIRMWARE_CXX_FLAGS_DEBUG "-g" CACHE STRING "Additional flags for firmware target (Debug config) c++ compiler (note: CMAKE_CXX_FLAGS_DEBUG is ignored for firmware/bootloader).")
52 # Python check
53 find_package("PythonInterp")
54 if(PYTHONINTERP_FOUND)
55   message(STATUS "Python found, version: ${PYTHON_VERSION_STRING}")
56 else()
57   message(WARNING "Python not found! Most firmware and simu flavors not buildable.")
58   set(LUA NO)
59 endif()
61 set(THIRDPARTY_DIR thirdparty)
62 set(LUA_DIR ${THIRDPARTY_DIR}/Lua/src)
63 set(COOS_DIR ${THIRDPARTY_DIR}/CoOS)
64 set(FATFS_DIR ${THIRDPARTY_DIR}/FatFs)
65 set(RADIO_BIN_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
67 configure_file(stamp.h.in stamp.h @ONLY)
69 add_subdirectory(translations)
70 add_subdirectory(bitmaps)
71 add_subdirectory(fonts)
73 set(EEPROM_VARIANT  0)
74 set(GVARS_VARIANT   1)
75 set(FRSKY_VARIANT   2)
76 set(3POS_VARIANT    4)
77 set(MAVLINK_VARIANT 8)
78 set(M2561_VARIANT   16384)
79 set(M128_VARIANT    32768)
81 set(FIRMWARE_DEPENDENCIES firmware_translations)
83 set(FATFS_SRC
84   ${FATFS_DIR}/ff.c
85   ${FATFS_DIR}/fattime.c
86   ${FATFS_DIR}/option/ccsbcs.c
89 if(PCB STREQUAL X12S OR PCB STREQUAL X10)
90   include(targets/horus/CMakeLists.txt)
91 elseif(PCB STREQUAL X9E OR PCB STREQUAL X9D+ OR PCB STREQUAL X9D OR PCB STREQUAL X7 OR PCB STREQUAL X7S)
92   include(targets/taranis/CMakeLists.txt)
93 elseif(PCB STREQUAL SKY9X OR PCB STREQUAL 9XRPRO OR PCB STREQUAL AR9X)
94   include(targets/sky9x/CMakeLists.txt)
95 elseif(PCB STREQUAL 9X OR PCB STREQUAL 9XR OR PCB STREQUAL 9X128 OR PCB STREQUAL 9XR128)
96   include(targets/9x/CMakeLists.txt)
97 elseif(PCB STREQUAL 9X2561)
98   set(ARCH AVR)
99   set(MCU atmega2561)
100   string(TOLOWER ${PCB} FLAVOUR)
101   set(EEPROM EEPROM_RLC)
102   set(SDCARD NO)
103   add_definitions(-DEEPROM_VARIANT=${M2561_VARIANT})
104   set(GUI_DIR 128x64)
105   set(TARGET_DIR 9x)
106   set(FIRMWARE_DEPENDENCIES ${FIRMWARE_DEPENDENCIES} 9x_bitmaps)
107   add_definitions(-DPCBSTD -DPCB${PCB} -DCPUM2561)
108   set(TARGET_SRC ${TARGET_SRC} board.cpp)
109   set(GUI_SRC
110     ${GUI_SRC}
111     model_inputs_mixes.cpp
112     radio_diagkeys.cpp
113     radio_diaganas.cpp)
114   if(SP22)
115     add_definitions(-DSP22)
116   endif()
117   if(PWM_BACKLIGHT)
118     add_definitions(-DPWM_BACKLIGHT)
119   endif()
120   set(FIRMWARE_TARGET_SRC ${FIRMWARE_TARGET_SRC} lcd_driver.cpp)
121 elseif(PCB STREQUAL GRUVIN9X)
122   include(targets/gruvin9x/CMakeLists.txt)
123 elseif(PCB STREQUAL MEGA2560)
124   include(targets/mega2560/CMakeLists.txt)
125 else()
126   message(FATAL_ERROR "Unknown PCB '${PCB}'")
127 endif()
129 if(NOT PCB STREQUAL 9XR AND NOT PCB STREQUAL 9XRPRO)
130   option(DBLKEYS "Double Keys" ON)
131   if(DBLKEYS)
132     add_definitions(-DDBLKEYS)
133   endif()
134 endif()
136 if(CPU_TYPE STREQUAL STM32F4)
137   include(targets/common/arm/stm32/f4/CMakeLists.txt)
138 endif()
140 if(CPU_TYPE STREQUAL STM32F2)
141   include(targets/common/arm/stm32/f2/CMakeLists.txt)
142 endif()
144 if(CPU_FAMILY STREQUAL STM32)
145   include(targets/common/arm/stm32/CMakeLists.txt)
146 endif()
148 if(ARCH STREQUAL ARM)
149   include(targets/common/arm/CMakeLists.txt)
150 else()
151   include(targets/common/avr/CMakeLists.txt)
152 endif()
154 include_directories(targets/${TARGET_DIR} ${THIRDPARTY_DIR})
156 foreach(LANGUAGE ${GUI_LANGUAGES})
157   if(TRANSLATIONS STREQUAL ${LANGUAGE})
158     add_definitions(-DTRANSLATIONS_${LANGUAGE} -DTRANSLATIONS="${LANGUAGE}")
159   endif()
160 endforeach()
162 set(SRC ${SRC} debug.cpp)
164 if(${EEPROM} STREQUAL SDCARD)
165   set(SRC ${SRC} storage/storage_common.cpp storage/sdcard_raw.cpp)
166 elseif(${EEPROM} STREQUAL EEPROM_RLC)
167   set(SRC ${SRC} storage/storage_common.cpp storage/eeprom_common.cpp storage/eeprom_rlc.cpp)
168   add_definitions(-DEEPROM -DEEPROM_RLC)
169 else()
170   set(SRC ${SRC} storage/storage_common.cpp storage/eeprom_common.cpp storage/eeprom_raw.cpp)
171   add_definitions(-DEEPROM -DEEPROM_RAW)
172 endif()
174 if(ARCH STREQUAL ARM AND NOT PCB STREQUAL X12S AND NOT PCB STREQUAL X10 AND NOT PCB STREQUAL FLAMENCO)
175   set(SRC ${SRC} storage/eeprom_conversions.cpp)
176 endif()
178 add_definitions(-DFLAVOUR="${FLAVOUR}")
180 include_directories(${CMAKE_CURRENT_SOURCE_DIR})
181 include_directories(${CMAKE_CURRENT_BINARY_DIR})
182 include_directories(${CMAKE_CURRENT_BINARY_DIR}/bitmaps/${GUI_DIR})
184 add_subdirectory(lua)
185 include(gui/CMakeLists.txt)
187 if(RAMBACKUP)
188   add_definitions(-DRAMBACKUP)
189   set(SRC ${SRC} storage/rambackup.cpp storage/rlc.cpp)
190 endif()
192 if(TEMPLATES)
193   add_definitions(-DTEMPLATES)
194   set(SRC ${SRC} templates.cpp)
195   set(GUI_SRC ${GUI_SRC} model_templates.cpp)
196 endif()
198 if(NOT LUA STREQUAL NO)
199   add_definitions(-DLUA)
200   if(LUA_COMPILER)
201     add_definitions(-DLUA_COMPILER)
202   endif()
203   if(NOT "${LUA_SCRIPT_LOAD_MODE}" STREQUAL "")
204     add_definitions(-DLUA_SCRIPT_LOAD_MODE="${LUA_SCRIPT_LOAD_MODE}")
205   endif()
206   include_directories(${LUA_DIR})
207   set(FIRMWARE_DEPENDENCIES ${FIRMWARE_DEPENDENCIES} ${LUA_EXPORT})
208   if(LUA STREQUAL YES)
209     add_definitions(-DLUA_MODEL_SCRIPTS)
210     set(GUI_SRC ${GUI_SRC} model_custom_scripts.cpp)
211   endif()
212   set(SRC ${SRC} lua/interface.cpp lua/api_general.cpp lua/api_lcd.cpp lua/api_model.cpp)
213   if(PCB STREQUAL X12S OR PCB STREQUAL X10)
214     set(SRC ${SRC} lua/widgets.cpp)
215   endif()
216   set(LUA_SRC lapi.c lcode.c lctype.c ldebug.c ldo.c ldump.c lfunc.c lgc.c llex.c lmem.c lobject.c lopcodes.c lparser.c
217     lstate.c lstring.c ltable.c lrotable.c ltm.c lundump.c lvm.c lzio.c linit.c
218     lbaselib.c lmathlib.c lbitlib.c loadlib.c lauxlib.c ltablib.c lcorolib.c liolib.c lstrlib.c
219     )
220   foreach(FILE ${LUA_SRC})
221     set(SRC ${SRC} ${LUA_DIR}/${FILE})
222   endforeach()
223   if(MSVC)
224     # silence lots of warnings regarding "insecure" use of functions (sprintf, strcpy, etc) from Lua code
225     set(WARNING_FLAGS "${WARNING_FLAGS} /D_CRT_SECURE_NO_WARNINGS")
226   endif()
227 endif()
229 if(HELI)
230   add_definitions(-DHELI)
231 endif()
233 if(FLIGHT_MODES)
234   add_definitions(-DFLIGHT_MODES)
235   set(GUI_SRC ${GUI_SRC} model_flightmodes.cpp)
236 endif()
238 if(CURVES)
239   add_definitions(-DCURVES)
240   set(SRC ${SRC} curves.cpp)
241 endif()
243 if(GVARS)
244   add_definitions(-DGVARS)
245   set(SRC ${SRC} gvars.cpp)
246   math(EXPR EEPROM_VARIANT ${EEPROM_VARIANT}+${GVARS_VARIANT})
247 endif()
249 if(FAI STREQUAL YES)
250   add_definitions(-DFAI)
251 elseif(FAI STREQUAL CHOICE)
252   add_definitions(-DFAI_CHOICE)
253 endif()
255 if(FAS_PROTOTYPE)
256   add_definitions(-DFAS_PROTOTYPE)
257 endif()
259 if(AUTOSOURCE)
260   add_definitions(-DAUTOSOURCE)
261 endif()
263 if(AUTOSWITCH)
264   add_definitions(-DAUTOSWITCH)
265 endif()
267 if(JITTER_MEASURE)
268   add_definitions(-DJITTER_MEASURE)
269 endif()
271 if(WATCHDOG_DISABLED)
272   add_definitions(-DWATCHDOG_DISABLED)
273 endif()
275 if(SIMU_AUDIO)
276   add_definitions(-DSIMU_AUDIO)
277 endif()
279 if(SDCARD)
280   add_definitions(-DSDCARD)
281   include_directories(${FATFS_DIR} ${FATFS_DIR}/option)
282   set(SRC ${SRC} sdcard.cpp rtc.cpp logs.cpp)
283   set(FIRMWARE_SRC ${FIRMWARE_SRC} ${FATFS_SRC})
284 endif()
286 if(SHUTDOWN_CONFIRMATION)
287   add_definitions(-DSHUTDOWN_CONFIRMATION)
288 endif()
290 if(PPM_UNIT STREQUAL US)
291   add_definitions(-DPPM_UNIT_US)
292 elseif(PPM_UNIT STREQUAL PERCENT_PREC1)
293   add_definitions(-DPPM_UNIT_PERCENT_PREC1)
294 else()
295   add_definitions(-DPPM_UNIT_PERCENT_PREC0)
296 endif()
298 if(PPM_CENTER_ADJUSTABLE)
299   add_definitions(-DPPM_CENTER_ADJUSTABLE)
300 endif()
302 if(PPM_LIMITS_SYMETRICAL)
303   add_definitions(-DPPM_LIMITS_SYMETRICAL)
304 endif()
306 if(OVERRIDE_CHANNEL_FUNCTION)
307   add_definitions(-DOVERRIDE_CHANNEL_FUNCTION)
308 endif()
310 if(DANGEROUS_MODULE_FUNCTIONS)
311   add_definitions(-DDANGEROUS_MODULE_FUNCTIONS)
312 endif()
314 if(SPLASH STREQUAL FRSKY)
315   add_definitions(-DSPLASH -DSPLASH_FRSKY)
316 elseif(NOT SPLASH STREQUAL OFF)
317   add_definitions(-DSPLASH)
318 endif()
320 if(NOT DEFAULT_MODE STREQUAL "")
321   add_definitions(-DDEFAULT_MODE=${DEFAULT_MODE})
322 endif()
324 if(TRACE_SIMPGMSPACE)
325   add_definitions(-DTRACE_SIMPGMSPACE)
326 endif()
328 if(TRACE_LUA_INTERNALS)
329   add_definitions(-DTRACE_LUA_INTERNALS_ENABLED)
330 endif()
332 if(BINDING_OPTIONS)
333   add_definitions(-DBINDING_OPTIONS)
334 endif()
336 if(FRSKY_STICKS)
337   add_definitions(-DFRSKY_STICKS)
338 endif()
340 if(EEPROM_VARIANT_NEEDED)
341   add_definitions(-DEEPROM_VARIANT=${EEPROM_VARIANT})
342 endif()
344 set(SRC
345   ${SRC}
346   opentx.cpp
347   functions.cpp
348   strhelpers.cpp
349   switches.cpp
350   mixer.cpp
351   stamp.cpp
352   timers.cpp
353   trainer_input.cpp
354   )
356 if(GUI)
357   add_definitions(-DGUI)
358   set(SRC
359     ${SRC}
360     keys.cpp
361     maths.cpp
362     translations.cpp
363     gui/gui_common.cpp
364     )
365   foreach(FILE ${GUI_SRC})
366     set(SRC ${SRC} gui/${GUI_DIR}/${FILE})
367   endforeach()
368   if(ARCH STREQUAL ARM)
369     set(SRC
370       ${SRC}
371       gui/gui_common_arm.cpp
372       )
373   endif()
374 endif()
376 foreach(FILE ${TARGET_SRC})
377   set(SRC targets/${TARGET_DIR}/${FILE} ${SRC})
378 endforeach()
380 foreach(FILE ${FIRMWARE_TARGET_SRC})
381   set(FIRMWARE_SRC ${FIRMWARE_SRC} targets/${TARGET_DIR}/${FILE})
382 endforeach()
384 foreach(FILE ${PULSES_SRC})
385   set(SRC ${SRC} pulses/${FILE})
386 endforeach()
388 add_definitions(-DCORRECT_NEGATIVE_SHIFTS)
390 if(NOT MSVC)
391   set(WARNING_FLAGS "${WARNING_FLAGS} -Wall -Wno-strict-aliasing -Wformat -Wreturn-type -Wunused -Wuninitialized -Wunknown-pragmas -Wno-switch -Wtype-limits")
392   if(WARNINGS_AS_ERRORS)
393     set(WARNING_FLAGS "${WARNING_FLAGS} -Werror")
394   endif(WARNINGS_AS_ERRORS)
395 else()
396   add_definitions(-DHAVE_STRUCT_TIMESPEC)  # this is for pthread.h
397   if(WARNINGS_AS_ERRORS)
398     set(WARNING_FLAGS "${WARNING_FLAGS} /WX")
399   endif(WARNINGS_AS_ERRORS)
400 endif()
402 add_subdirectory(targets/simu)
403 if(NOT MSVC)
404   add_subdirectory(tests)
405 endif()
407 set(SRC ${SRC} ${FIRMWARE_SRC})
410 ##### firmware target #####
412 option(FIRMWARE_TARGET "Configure Firmware target (can be turned of for compiling Companion only)" ON)
413 if(NOT FIRMWARE_TARGET)
414   message(STATUS "firmware target disabled")
415   return()
416 endif()
418 set(CMAKE_EXECUTABLE_SUFFIX ".elf")
419 # trick to remove the -rdynamic and --out-implib issues
420 set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
421 set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
422 # similar for -mmacosx-version-min="
423 set(CMAKE_C_OSX_DEPLOYMENT_TARGET_FLAG "")
424 set(CMAKE_CXX_OSX_DEPLOYMENT_TARGET_FLAG "")
425 # reset some CMake default flags which assume optimization levels/etc
426 set(CMAKE_C_FLAGS "${FIRMWARE_C_FLAGS}")
427 set(CMAKE_C_FLAGS_DEBUG "${FIRMWARE_C_FLAGS_DEBUG}")
428 set(CMAKE_C_FLAGS_RELEASE "")
429 set(CMAKE_C_FLAGS_MINSIZEREL "")
430 set(CMAKE_C_FLAGS_RELWITHDEBINFO "")
431 set(CMAKE_CXX_FLAGS "${FIRMWARE_CXX_FLAGS}")
432 set(CMAKE_CXX_FLAGS_DEBUG "${FIRMWARE_CXX_FLAGS_DEBUG}")
433 set(CMAKE_CXX_FLAGS_RELEASE "")
434 set(CMAKE_CXX_FLAGS_MINSIZEREL "")
435 set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "")
436 # customize linker command
437 set(CMAKE_EXE_LINKER_FLAGS "")
438 set(CMAKE_C_LINK_EXECUTABLE "<CMAKE_C_COMPILER> <FLAGS> <LINK_FLAGS> <OBJECTS>  -o <TARGET>")
439 set(CMAKE_CXX_LINK_EXECUTABLE "<CMAKE_CXX_COMPILER> <FLAGS> <LINK_FLAGS> <OBJECTS>  -o <TARGET>")
441 use_cxx11()  # ensure gnu++11 in CXX_FLAGS with CMake < 3.1
443 find_program(BASH bash HINTS "c:/cygwin/bin/" "c:/msys/bin/" DOC "bash shell for firmware size report (eg. c:/cygwin/bin/bash.exe on Windows).")
445 if(NOT MSVC)
446   set(OPT s)
448   if(ARCH STREQUAL ARM)
450     enable_language(ASM)
451     set(CMAKE_C_COMPILER arm-none-eabi-gcc)
452     set(CMAKE_CXX_COMPILER arm-none-eabi-g++)
453     set(CMAKE_ASM_COMPILER arm-none-eabi-as)
455     set(CMAKE_SYSTEM_NAME Generic)
456     set(CMAKE_SYSTEM_VERSION 1)
457     set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> -o <OBJECT> <SOURCE>")
459     set(COMMON_FLAGS "-mcpu=${MCU} -mthumb -fomit-frame-pointer -fverbose-asm -Wa,-ahlms=firmware.lst -O${OPT} -gdwarf-2 -DHSE_VALUE=${HSE_VALUE} -fno-exceptions -fdata-sections -ffunction-sections ${WARNING_FLAGS}")
460     set(COMMON_FLAGS "${COMMON_FLAGS} ${FPU_FLAGS}")
462     set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COMMON_FLAGS} -Wimplicit")
463     set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COMMON_FLAGS}")
465     # these are in addition to CMAKE_CXX_FLAGS
466     set(CMAKE_EXE_LINKER_FLAGS "-lm -T${RADIO_SRC_DIRECTORY}/${LINKER_SCRIPT} -Wl,-Map=firmware.map,--cref,--no-warn-mismatch,--gc-sections")
467     if(SEMIHOSTING)
468       add_definitions(-DSEMIHOSTING)
469       set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --specs=rdimon.specs")
470     endif()
471     # Use newlib nano, which saves a few kilobytes.
472     if(NOT NANO STREQUAL NO)
473       set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --specs=nano.specs")
474       if(NOT LUA STREQUAL NO)
475         # Lua needs %g and %f
476         set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -u _printf_float -u _scanf_float")
477       endif()
478       # Nano's malloc does work well with lua, use our own
479       add_definitions(-DUSE_BIN_ALLOCATOR)
480       set(SRC ${SRC} bin_allocator.cpp)
481     endif()
483     
484     if(PCB STREQUAL X9D OR PCB STREQUAL X9D+ OR PCB STREQUAL X9E OR PCB STREQUAL X7 OR PCB STREQUAL X7S)
485       add_subdirectory(targets/${TARGET_DIR}/bootloader)
486       include_directories(${CMAKE_CURRENT_BINARY_DIR}/targets/${TARGET_DIR}/bootloader)
487       set(FIRMWARE_DEPENDENCIES ${FIRMWARE_DEPENDENCIES} bootloader)
488     elseif(OPENRC_BOOTLOADER)
489       # We fetch Mike's bootloader as it is not included inside OpenTX
490       message(STATUS "Downloading Mike's bootloader: https://github.com/MikeBland/OpenRcBootloader/releases/download/V1.9/${OPENRC_BOOTLOADER}")
491       file(DOWNLOAD https://github.com/MikeBland/OpenRcBootloader/releases/download/V1.9/${OPENRC_BOOTLOADER} ${CMAKE_CURRENT_BINARY_DIR}/bootloader.lbm STATUS status)
492       list(GET status 0 error_code)
493       if(error_code)
494         list(GET status 1 error_message)
495         message(FATAL_ERROR "Download failed: ${error_message}")
496       endif()
497     endif()
499     add_executable(firmware ${SRC} ${FIRMWARE_HEADERS})
500     link_libraries(firmware -lstdc++)
501     add_dependencies(firmware ${FIRMWARE_DEPENDENCIES})
503     add_custom_command(
504       TARGET firmware POST_BUILD
505       COMMAND arm-none-eabi-objcopy -O binary firmware.elf firmware.bin
506       WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
507     )
509     find_program(GAWK gawk HINTS "c:/cygwin/bin/" "c:/msys/bin/" DOC "gawk for firmware size report.")  # OS X might only have "awk"
510     if (BASH AND GAWK)
511       add_custom_target(firmware-size
512         COMMAND ${BASH} -kc '${RADIO_DIRECTORY}/util/elf-size-report.sh --mcu=${CPU_TYPE_FULL} ${SIZE_TARGET_MEM_DEFINE} firmware.elf'
513         DEPENDS firmware
514         WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
515         )
516     else()
517       add_custom_target(firmware-size
518         COMMAND arm-none-eabi-size -A firmware.elf
519         DEPENDS firmware
520         WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
521         )
522     endif()
524   else()  # AVR
526     set(CMAKE_C_COMPILER avr-gcc)
527     set(CMAKE_CXX_COMPILER avr-gcc)
529     set(COMMON_FLAGS "-mmcu=${MCU} -DF_CPU=16000000UL -O${OPT} -gdwarf-2 -fno-exceptions -flto -fwhole-program -fno-inline-small-functions -mstrict-X ${WARNING_FLAGS}")
530     set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COMMON_FLAGS}")
531     set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COMMON_FLAGS}")
532     set(CMAKE_EXE_LINKER_FLAGS "-Wno-uninitialized")  # bogus "uninitialized" warnings from ld
534     include_directories(storage gui/${GUI_DIR})
536     set(ALLSRC ${PROJECT_BINARY_DIR}/allsrc.cpp)
537     if (BASH AND NOT WIN32)
538       add_custom_command(
539         OUTPUT ${ALLSRC}
540         COMMAND ${BASH} -kc 'rm -f ${ALLSRC}\; for f in ${SRC}\; do echo "\\# 1 \\\"$$f\\\"" >> ${ALLSRC}\; cat "$$f" >> ${ALLSRC}\; done'
541         WORKING_DIRECTORY ${RADIO_SRC_DIRECTORY}
542         DEPENDS ${SRC}
543         )
544     elseif(WIN32)
545       string(REPLACE "/" "\\" SRC_WIN "${SRC}")
546       string(REPLACE "/" "\\" ALLSRC_WIN "${ALLSRC}")
547       set(ALLSRC_BAT
548           "setlocal EnableDelayedExpansion"
549           "del \"${ALLSRC_WIN}\""
550           "for %%f in (${SRC_WIN}) do ("
551             "set p=\"%%f\""
552             "set p=!p:^\\=/! \necho \# 1 !p! >> \"${ALLSRC_WIN}\""
553             "type %%f >> \"${ALLSRC_WIN}\""
554           ")\n"
555         )
556       string(REPLACE ";" "\n" ALLSRC_BAT "${ALLSRC_BAT}")
557       file(WRITE "${ALLSRC}.bat" "${ALLSRC_BAT}")
558       add_custom_command(
559         OUTPUT ${ALLSRC}
560         COMMAND "${ALLSRC}.bat"
561         WORKING_DIRECTORY ${RADIO_SRC_DIRECTORY}
562         DEPENDS ${SRC}
563         )
564     else()
565       set(ALLSRC ${SRC})
566     endif()
567     add_executable(firmware ${ALLSRC})
569     add_dependencies(firmware ${FIRMWARE_DEPENDENCIES})
571     add_custom_command(
572       TARGET firmware POST_BUILD
573       COMMAND avr-objcopy -O ihex -R .eeprom firmware.elf firmware.hex
574       WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
575       )
577     add_custom_target(firmware.lss
578       COMMAND avr-objdump -h -S firmware.elf > firmware.lss
579       DEPENDS firmware
580       WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
581       )
583     add_custom_target(firmware-size
584       COMMAND avr-size --format=avr --mcu=${MCU} firmware.elf
585       DEPENDS firmware
586       WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
587       )
589   endif()  # ARM or AVR
591   if(CPU_FAMILY STREQUAL STM32)
592     add_custom_target(flash
593       COMMAND dfu-util --alt 0 --dfuse-address 0x08000000:leave -d 0483:df11 -D firmware.bin
594       DEPENDS firmware
595       WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
596     )
598     add_custom_target(jtag-flash
599       COMMAND st-flash --reset write firmware.bin 0x8000000
600       DEPENDS firmware
601       WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
602       )
603   else()
604     add_custom_target(flash
605       COMMAND avrdude -c usbasp -p ${AVRDUDE_MCU} -U flash:w:firmware.hex:i
606       DEPENDS firmware
607       WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
608       )
609   endif()
611   PrintTargetReport("firmware")
613 endif(NOT MSVC)