fix delayed save + exclude manual mode
[inav.git] / cmake / at32.cmake
blobaa902593e94f6e1b947d892671860a7d0b45de2f
1 include(at32-bootloader)
2 include(at32f4)
4 include(CMakeParseArguments)
6 option(DEBUG_HARDFAULTS "Enable debugging of hard faults via custom handler")
7 option(SEMIHOSTING "Enable semihosting")
9 message("-- DEBUG_HARDFAULTS: ${DEBUG_HARDFAULTS}, SEMIHOSTING: ${SEMIHOSTING}")
11 set(CMSIS_DIR "${MAIN_LIB_DIR}/lib/main/AT32F43x/Drivers/CMSIS")
12 set(CMSIS_INCLUDE_DIR "${CMSIS_DIR}/cm4/core_support") 
13 # DSP use common
14 set(CMSIS_DSP_DIR "${MAIN_LIB_DIR}/main/CMSIS/DSP")
15 set(CMSIS_DSP_INCLUDE_DIR "${CMSIS_DSP_DIR}/Include")
17 set(CMSIS_DSP_SRC
18     BasicMathFunctions/arm_scale_f32.c
19     BasicMathFunctions/arm_sub_f32.c
20     BasicMathFunctions/arm_mult_f32.c
21     TransformFunctions/arm_rfft_fast_f32.c
22     TransformFunctions/arm_cfft_f32.c
23     TransformFunctions/arm_rfft_fast_init_f32.c
24     TransformFunctions/arm_cfft_radix8_f32.c
25     TransformFunctions/arm_bitreversal2.S
26     CommonTables/arm_common_tables.c
27     ComplexMathFunctions/arm_cmplx_mag_f32.c
28     StatisticsFunctions/arm_max_f32.c
30 list(TRANSFORM CMSIS_DSP_SRC PREPEND "${CMSIS_DSP_DIR}/Source/")
32 set(AT32_STARTUP_DIR "${MAIN_SRC_DIR}/startup")
34 main_sources(AT32_VCP_SRC
35     drivers/serial_usb_vcp_at32f43x.c
36     drivers/usb_io.c
38 # SDCARD not supported yet
39 main_sources(AT32_SDCARD_SRC
40     drivers/sdcard/sdcard.c
41     drivers/sdcard/sdcard_spi.c
42     drivers/sdcard/sdcard_sdio.c
43     drivers/sdcard/sdcard_standard.c
46 # XXX: This code is not STM32 specific
47 main_sources(AT32_ASYNCFATFS_SRC
48     io/asyncfatfs/asyncfatfs.c
49     io/asyncfatfs/fat_standard.c
52 main_sources(AT32_MSC_SRC
53     msc/at32_msc_diskio.c 
54     msc/emfat.c 
55     msc/emfat_file.c
58 set(AT32_INCLUDE_DIRS
59     "${CMSIS_INCLUDE_DIR}"
60     "${CMSIS_DSP_INCLUDE_DIR}"
61     "${MAIN_SRC_DIR}/target"
64 set(AT32_DEFINITIONS
66 set(AT32_DEFAULT_HSE_MHZ 8)
67 set(AT32_LINKER_DIR "${MAIN_SRC_DIR}/target/link")
68 set(AT32_COMPILE_OPTIONS
69     -ffunction-sections
70     -fdata-sections
71     -fno-common
74 set(AT32_LINK_LIBRARIES
75     -lm
76     -lc
79 if(SEMIHOSTING)
80     list(APPEND AT32_LINK_LIBRARIES --specs=rdimon.specs -lrdimon)
81     list(APPEND AT32_DEFINITIONS SEMIHOSTING)
82 else()
83     list(APPEND AT32_LINK_LIBRARIES -lnosys)
84 endif()
86 set(AT32_LINK_OPTIONS
87     #-nostartfiles
88     --specs=nano.specs
89     -static
90     -Wl,-gc-sections
91     -Wl,-L${AT32_LINKER_DIR}
92     -Wl,--cref
93     -Wl,--no-wchar-size-warning
94     -Wl,--print-memory-usage
96 # Get target features
97 macro(get_at32_target_features output_var dir target_name)
98     execute_process(COMMAND "${CMAKE_C_COMPILER}" -E -dD -D${ARGV2} "${ARGV1}/target.h"
99         ERROR_VARIABLE _errors
100         RESULT_VARIABLE _result
101         OUTPUT_STRIP_TRAILING_WHITESPACE
102         OUTPUT_VARIABLE _contents)
104     if(NOT _result EQUAL 0)
105         message(FATAL_ERROR "error extracting features for AT32 target ${ARGV2}: ${_errors}")
106     endif()
108     string(REGEX MATCH "#define[\t ]+USE_VCP" HAS_VCP ${_contents})
109     if(HAS_VCP)
110         list(APPEND ${ARGV0} VCP)
111     endif()
112     string(REGEX MATCH "define[\t ]+USE_FLASHFS" HAS_FLASHFS ${_contents})
113     if(HAS_FLASHFS)
114         list(APPEND ${ARGV0} FLASHFS)
115     endif()
116     string(REGEX MATCH "define[\t ]+USE_SDCARD" HAS_SDCARD ${_contents})
117     if (HAS_SDCARD)
118         list(APPEND ${ARGV0} SDCARD)
119         string(REGEX MATCH "define[\t ]+USE_SDCARD_SDIO" HAS_SDIO ${_contents})
120         if (HAS_SDIO)
121             list(APPEND ${ARGV0} SDIO)
122         endif()
123     endif()
124     if(HAS_FLASHFS OR HAS_SDCARD)
125         list(APPEND ${ARGV0} MSC)
126     endif()
127 endmacro()
129 function(get_at32_flash_size out size)
130     # 4: 16, 6: 32, 8: 64, B: 128, C: 256, D: 384, E: 512, F: 768, G: 1024, H: 1536, I: 2048 KiB
131     string(TOUPPER ${size} s)
132     if(${s} STREQUAL "4")
133         set(${out} 16 PARENT_SCOPE)
134         return()
135     endif()
136     if(${s} STREQUAL "6")
137         set(${out} 32 PARENT_SCOPE)
138         return()
139     endif()
140     if(${s} STREQUAL "8")
141         set(${out} 64 PARENT_SCOPE)
142         return()
143     endif()
144     if(${s} STREQUAL "8")
145         set(${out} 64 PARENT_SCOPE)
146         return()
147     endif()
148     if(${s} STREQUAL "B")
149         set(${out} 128 PARENT_SCOPE)
150         return()
151     endif()
152     if(${s} STREQUAL "C")
153         set(${out} 256 PARENT_SCOPE)
154         return()
155     endif()
156     if(${s} STREQUAL "D")
157         set(${out} 384 PARENT_SCOPE)
158         return()
159     endif()
160     if(${s} STREQUAL "E")
161         set(${out} 512 PARENT_SCOPE)
162         return()
163     endif()
164     if(${s} STREQUAL "F")
165         set(${out} 768 PARENT_SCOPE)
166         return()
167     endif()
168     if(${s} STREQUAL "G")
169         set(${out} 1024 PARENT_SCOPE)
170         return()
171     endif()
172     if(${s} STREQUAL "H")
173         set(${out} 1536 PARENT_SCOPE)
174         return()
175     endif()
176     if(${s} STREQUAL "I")
177         set(${out} 2048 PARENT_SCOPE)
178         return()
179     endif()
180 endfunction()
182 function(add_hex_target name exe hex)
183     add_custom_target(${name} ALL
184         cmake -E env PATH="$ENV{PATH}"
185         # TODO: Overriding the start address with --set-start 0x08000000
186         # seems to be required due to some incorrect assumptions about .hex
187         # files in the configurator. Verify wether that's the case and fix
188         # the bug in configurator or delete this comment.
189         ${CMAKE_OBJCOPY} -Oihex --set-start 0x08000000 $<TARGET_FILE:${exe}> ${hex}
190         BYPRODUCTS ${hex}
191     )
192 endfunction()
194 function(add_bin_target name exe bin)
195     add_custom_target(${name}
196         cmake -E env PATH="$ENV{PATH}"
197         ${CMAKE_OBJCOPY} -Obinary $<TARGET_FILE:${exe}> ${bin}
198         BYPRODUCTS ${bin}
199     )
200 endfunction()
202 function(generate_map_file target)
203     if(CMAKE_VERSION VERSION_LESS 3.15)
204         set(map "$<TARGET_FILE:${target}>.map")
205     else()
206         set(map "$<TARGET_FILE_DIR:${target}>/$<TARGET_FILE_BASE_NAME:${target}>.map")
207     endif()
208     target_link_options(${target} PRIVATE "-Wl,-Map,${map}")
209 endfunction()
211 function(set_linker_script target script)
212     set(script_path ${AT32_LINKER_DIR}/${args_LINKER_SCRIPT}.ld)
213     if(NOT EXISTS ${script_path})
214         message(FATAL_ERROR "linker script ${script_path} doesn't exist")
215     endif()
216     set_target_properties(${target} PROPERTIES LINK_DEPENDS ${script_path})
217     target_link_options(${elf_target} PRIVATE -T${script_path})
218 endfunction()
220 function(add_at32_executable)
221     cmake_parse_arguments(
222         args
223         # Boolean arguments
224         ""
225         # Single value arguments
226         "FILENAME;NAME;OPTIMIZATION;OUTPUT_BIN_FILENAME;OUTPUT_HEX_FILENAME;OUTPUT_TARGET_NAME"
227         # Multi-value arguments
228         "COMPILE_DEFINITIONS;COMPILE_OPTIONS;INCLUDE_DIRECTORIES;LINK_OPTIONS;LINKER_SCRIPT;SOURCES"
229         # Start parsing after the known arguments
230         ${ARGN}
231     )
232     set(elf_target ${args_NAME}.elf)
233     add_executable(${elf_target})
234     target_sources(${elf_target} PRIVATE ${args_SOURCES})
235     target_include_directories(${elf_target} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${args_INCLUDE_DIRECTORIES} ${AT32_INCLUDE_DIRS})
236     target_compile_definitions(${elf_target} PRIVATE ${args_COMPILE_DEFINITIONS})
237     target_compile_options(${elf_target} PRIVATE ${AT32_COMPILE_OPTIONS} ${args_COMPILE_OPTIONS})
238     if(WARNINGS_AS_ERRORS)
239         target_compile_options(${elf_target} PRIVATE -Werror)
240     endif()
241     if (IS_RELEASE_BUILD)
242         target_compile_options(${elf_target} PRIVATE ${args_OPTIMIZATION})
243         target_link_options(${elf_target} PRIVATE ${args_OPTIMIZATION})
244     endif()
245     target_link_libraries(${elf_target} PRIVATE ${AT32_LINK_LIBRARIES})
246     target_link_options(${elf_target} PRIVATE ${AT32_LINK_OPTIONS} ${args_LINK_OPTIONS})
247     generate_map_file(${elf_target})
248     set_linker_script(${elf_target} ${args_LINKER_SCRIPT})
249     if(args_FILENAME)
250         set(basename ${CMAKE_BINARY_DIR}/${args_FILENAME})
251         set(hex_filename ${basename}.hex)
252         add_hex_target(${args_NAME} ${elf_target} ${hex_filename})
253         set(bin_filename ${basename}.bin)
254         add_bin_target(${args_NAME}.bin ${elf_target} ${bin_filename})
255     endif()
256     if(args_OUTPUT_BIN_FILENAME)
257         set(${args_OUTPUT_BIN_FILENAME} ${bin_filename} PARENT_SCOPE)
258     endif()
259     if(args_OUTPUT_TARGET_NAME)
260         set(${args_OUTPUT_TARGET_NAME} ${elf_target} PARENT_SCOPE)
261     endif()
262     if(args_OUTPUT_HEX_FILENAME)
263         set(${args_OUTPUT_HEX_FILENAME} ${hex_filename} PARENT_SCOPE)
264     endif()
265 endfunction()
267 #  Main function of AT32 
268 function(target_at32)
269     if(NOT arm-none-eabi STREQUAL TOOLCHAIN)
270         return()
271     endif()
272     # Parse keyword arguments
273     cmake_parse_arguments(
274         args
275         # Boolean arguments
276         "DISABLE_MSC;BOOTLOADER"
277         # Single value arguments
278         "HSE_MHZ;LINKER_SCRIPT;NAME;OPENOCD_TARGET;OPTIMIZATION;STARTUP;SVD"
279         # Multi-value arguments
280         "COMPILE_DEFINITIONS;COMPILE_OPTIONS;INCLUDE_DIRECTORIES;LINK_OPTIONS;SOURCES;MSC_SOURCES;MSC_INCLUDE_DIRECTORIES;VCP_SOURCES;VCP_INCLUDE_DIRECTORIES"
281         # Start parsing after the known arguments
282         ${ARGN}
283     )
284     set(name ${args_NAME})
286     if (args_HSE_MHZ)
287         set(hse_mhz ${args_HSE_MHZ})
288     else()
289         set(hse_mhz ${AT32_DEFAULT_HSE_MHZ})
290     endif()
292     set(target_sources ${AT32_STARTUP_DIR}/${args_STARTUP})
293     list(APPEND target_sources ${args_SOURCES})
294     file(GLOB target_c_sources "${CMAKE_CURRENT_SOURCE_DIR}/*.c")
295     file(GLOB target_h_sources "${CMAKE_CURRENT_SOURCE_DIR}/*.h")
296     list(APPEND target_sources ${target_c_sources} ${target_h_sources})
298     set(target_include_directories ${args_INCLUDE_DIRECTORIES})
300     set(target_definitions ${AT32_DEFINITIONS} ${COMMON_COMPILE_DEFINITIONS})
302     get_at32_target_features(features "${CMAKE_CURRENT_SOURCE_DIR}" ${name})
303     set_property(TARGET ${elf_target} PROPERTY FEATURES ${features})
305     if(VCP IN_LIST features)
306         list(APPEND target_sources ${AT32_VCP_SRC} ${args_VCP_SOURCES})
307         list(APPEND target_include_directories ${args_VCP_INCLUDE_DIRECTORIES})
308     endif()
309     if(SDCARD IN_LIST features)
310         list(APPEND target_sources ${AT32_SDCARD_SRC} ${AT32_ASYNCFATFS_SRC})
311     endif()
313     set(msc_sources)
314     if(NOT args_DISABLE_MSC AND MSC IN_LIST features)
315         list(APPEND target_include_directories ${args_MSC_INCLUDE_DIRECTORIES})
316         list(APPEND msc_sources ${AT32_MSC_SRC} ${args_MSC_SOURCES})
317         list(APPEND target_definitions USE_USB_MSC)
318         if(FLASHFS IN_LIST features)
319             list(APPEND msc_sources ${AT32_MSC_FLASH_SRC})
320         endif()
321         if (SDCARD IN_LIST features)
322             list(APPEND msc_sources ${AT32_MSC_SDCARD_SRC})
323         endif()
324     endif()
326     math(EXPR hse_value "${hse_mhz} * 1000000")
327     list(APPEND target_definitions "HSE_VALUE=${hse_value}")
328     if(args_COMPILE_DEFINITIONS)
329         list(APPEND target_definitions ${args_COMPILE_DEFINITIONS})
330     endif()
331     if(DEBUG_HARDFAULTS)
332         list(APPEND target_definitions DEBUG_HARDFAULTS)
333     endif()
335     string(TOLOWER ${PROJECT_NAME} lowercase_project_name)
336     set(binary_name ${lowercase_project_name}_${FIRMWARE_VERSION}_${name})
337     if(DEFINED BUILD_SUFFIX AND NOT "" STREQUAL "${BUILD_SUFFIX}")
338         set(binary_name "${binary_name}_${BUILD_SUFFIX}")
339     endif()
341     # Main firmware
342     add_at32_executable(
343         NAME ${name}
344         FILENAME ${binary_name}
345         SOURCES ${target_sources} ${msc_sources} ${CMSIS_DSP_SRC} ${COMMON_SRC}
346         COMPILE_DEFINITIONS ${target_definitions}
347         COMPILE_OPTIONS ${args_COMPILE_OPTIONS}
348         INCLUDE_DIRECTORIES ${target_include_directories}
349         LINK_OPTIONS ${args_LINK_OPTIONS}
350         LINKER_SCRIPT ${args_LINKER_SCRIPT}
351         OPTIMIZATION ${args_OPTIMIZATION}
353         OUTPUT_BIN_FILENAME main_bin_filename
354         OUTPUT_HEX_FILENAME main_hex_filename
355         OUTPUT_TARGET_NAME main_target_name
357     )
359     set_property(TARGET ${main_target_name} PROPERTY OPENOCD_TARGET ${args_OPENOCD_TARGET})
360     set_property(TARGET ${main_target_name} PROPERTY OPENOCD_DEFAULT_INTERFACE atlink)
361     set_property(TARGET ${main_target_name} PROPERTY SVD ${args_SVD})
363     setup_firmware_target(${main_target_name} ${name} ${ARGN})
365     if(args_BOOTLOADER)
366         # Bootloader for the target
367         set(bl_suffix _bl)
368         add_at32_executable(
369             NAME ${name}${bl_suffix}
370             FILENAME ${binary_name}${bl_suffix}
371             SOURCES ${target_sources} ${BOOTLOADER_SOURCES}
372             COMPILE_DEFINITIONS ${target_definitions} BOOTLOADER MSP_FIRMWARE_UPDATE
373             COMPILE_OPTIONS ${args_COMPILE_OPTIONS}
374             INCLUDE_DIRECTORIES ${target_include_directories}
375             LINK_OPTIONS ${args_LINK_OPTIONS}
376             LINKER_SCRIPT ${args_LINKER_SCRIPT}${bl_suffix}
377             OPTIMIZATION ${args_OPTIMIZATION}
379             OUTPUT_BIN_FILENAME bl_bin_filename
380             OUTPUT_HEX_FILENAME bl_hex_filename
381             OUTPUT_TARGET_NAME bl_target_name
382         )
383         setup_executable(${bl_target_name} ${name})
385         # Main firmware, but for running with the bootloader
386         set(for_bl_suffix _for_bl)
387         add_at32_executable(
388             NAME ${name}${for_bl_suffix}
389             FILENAME ${binary_name}${for_bl_suffix}
390             SOURCES ${target_sources} ${msc_sources} ${CMSIS_DSP_SRC} ${COMMON_SRC}
391             COMPILE_DEFINITIONS ${target_definitions} MSP_FIRMWARE_UPDATE
392             COMPILE_OPTIONS ${args_COMPILE_OPTIONS}
393             INCLUDE_DIRECTORIES ${target_include_directories}
394             LINK_OPTIONS ${args_LINK_OPTIONS}
395             LINKER_SCRIPT ${args_LINKER_SCRIPT}${for_bl_suffix}
396             OPTIMIZATION ${args_OPTIMIZATION}
398             OUTPUT_BIN_FILENAME for_bl_bin_filename
399             OUTPUT_HEX_FILENAME for_bl_hex_filename
400             OUTPUT_TARGET_NAME for_bl_target_name
401         )
402         setup_executable(${for_bl_target_name} ${name})
404         # Combined with bootloader and main firmware
405         set(with_bl_suffix _with_bl)
406         set(combined_hex ${CMAKE_BINARY_DIR}/${binary_name}${with_bl_suffix}.hex)
407         set(with_bl_target ${name}${with_bl_suffix})
408         add_custom_target(${with_bl_target}
409             ${CMAKE_SOURCE_DIR}/src/utils/combine_tool ${bl_bin_filename} ${for_bl_bin_filename} ${combined_hex}
410             BYPRODUCTS ${combined_hex}
411         )
412         add_dependencies(${with_bl_target} ${bl_target_name} ${for_bl_target_name})
413     endif()
415     # clean_<target>
416     set(generator_cmd "")
417     if (CMAKE_GENERATOR STREQUAL "Unix Makefiles")
418         set(generator_cmd "make")
419     elseif(CMAKE_GENERATOR STREQUAL "Ninja")
420         set(generator_cmd "ninja")
421     endif()
422     if (NOT generator_cmd STREQUAL "")
423         set(clean_target "clean_${name}")
424         add_custom_target(${clean_target}
425             WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
426             COMMAND ${generator_cmd} clean
427             COMMENT "Removing intermediate files for ${name}")
428         set_property(TARGET ${clean_target} PROPERTY
429             EXCLUDE_FROM_ALL 1
430             EXCLUDE_FROM_DEFAULT_BUILD 1)
431     endif()
432 endfunction()