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