Procházet zdrojové kódy

Allow choosing FreeRTOS from STM32Cube

Robin Mueller před 4 roky
rodič
revize
22339cc837
2 změnil soubory, kde provedl 176 přidání a 48 odebrání
  1. 27 1
      README.md
  2. 149 47
      cmake/FindFreeRTOS.cmake

+ 27 - 1
README.md

@@ -212,7 +212,10 @@ Typical usage:
 
 ```cmake
 find_package(FreeRTOS COMPONENTS ARM_CM4F REQUIRED)
-target_link_libraries(... FreeRTOS::ARM_CM4F)
+target_link_libraries(${TARGET_NAME} PRIVATE
+    ...
+    FreeRTOS::ARM_CM4F
+)
 ```
 
 The following FreeRTOS ports are supported: `ARM_CM0`, `ARM_CM3`, `ARM_CM4F`, `ARM_CM7`.
@@ -224,3 +227,26 @@ Other FreeRTOS libraries:
 * `FreeRTOS::StreamBuffer` - stream buffer (`stream_buffer.c`)
 * `FreeRTOS::Timers` - timers (`timers.c`)
 * `FreeRTOS::Heap::<N>` - heap implementation (`heap_<N>.c`), `<N>`: [1-5]
+
+The STM32Cube packages can contain the FreeRTOS source package and a CMSIS RTOS and RTOS_V2
+implementation. You can specify to use CMSIS with a `CMSIS` target and by finding the CMSIS
+`RTOS` package.
+
+Typical usage for a H7 device when using the M7 core with CMSIS `RTOS`:
+
+```cmake
+find_package(CMSIS COMPONENTS STM32H743ZI STM32H7_M7 RTOS REQUIRED)
+target_link_libraries(${TARGET_NAME} PRIVATE
+    ...
+    FreeRTOS::ARM_CM7
+    CMSIS::STM32::H7::M7::RTOS
+)
+```
+
+The following targets are available in general:
+
+* `CMSIS::STM32::<Family>::RTOS`
+* `CMSIS::STM32::<Family>::RTOS_V2`
+
+For the multi-core architectures, you have to specify both family and core like specified in the
+example.

+ 149 - 47
cmake/FindFreeRTOS.cmake

@@ -1,9 +1,7 @@
+set(FreeRTOS_PORTS ARM_CM0 ARM_CM3 ARM_CM4F ARM_CM7)
 if(NOT FreeRTOS_FIND_COMPONENTS)
-    set(FreeRTOS_FIND_COMPONENTS
-        ARM_CM0 ARM_CM3 ARM_CM4F ARM_CM7
-    )
+    set(FreeRTOS_FIND_COMPONENTS ${FreeRTOS_PORTS})
 endif()
-list(REMOVE_DUPLICATES FreeRTOS_FIND_COMPONENTS)
 
 set(FreeRTOS_HEAPS 1 2 3 4 5)
 
@@ -46,41 +44,30 @@ if(NOT (TARGET FreeRTOS))
     target_include_directories(FreeRTOS INTERFACE "${FreeRTOS_COMMON_INCLUDE}")
 endif()
 
-if(NOT (TARGET FreeRTOS::Coroutine))
-    add_library(FreeRTOS::Coroutine INTERFACE IMPORTED)
-    target_sources(FreeRTOS::Coroutine INTERFACE "${FreeRTOS_SOURCE_DIR}/croutine.c")
-    target_link_libraries(FreeRTOS::Coroutine INTERFACE FreeRTOS)
-endif()
+foreach(COMP ${FreeRTOS_FIND_COMPONENTS})
+    string(TOUPPER ${COMP} COMP)
+    string(REGEX MATCH "^STM32([A-Z][0-9])([0-9A-Z][0-9][A-Z][0-9A-Z])?_?(M[47])?.*$" FAMILY_COMP ${COMP})
+    if(CMAKE_MATCH_1)
+        list(APPEND FreeRTOS_FIND_COMPONENTS_FAMILIES ${FAMILY_COMP})
+        continue()
+    endif()
 
-if(NOT (TARGET FreeRTOS::EventGroups))
-    add_library(FreeRTOS::EventGroups INTERFACE IMPORTED)
-    target_sources(FreeRTOS::EventGroups INTERFACE "${FreeRTOS_SOURCE_DIR}/event_groups.c")
-    target_link_libraries(FreeRTOS::EventGroups INTERFACE FreeRTOS)
-endif()
+    list(APPEND FreeRTOS_FIND_COMPONENTS_PORTS ${COMP})
+endforeach()
 
-if(NOT (TARGET FreeRTOS::StreamBuffer))
-    add_library(FreeRTOS::StreamBuffer INTERFACE IMPORTED)
-    target_sources(FreeRTOS::StreamBuffer INTERFACE "${FreeRTOS_SOURCE_DIR}/stream_buffer.c")
-    target_link_libraries(FreeRTOS::StreamBuffer INTERFACE FreeRTOS)
+if(NOT FreeRTOS_FIND_COMPONENTS_PORTS)
+    set(FreeRTOS_FIND_COMPONENTS_PORTS ${FreeRTOS_PORTS})
 endif()
 
-if(NOT (TARGET FreeRTOS::Timers))
-    add_library(FreeRTOS::Timers INTERFACE IMPORTED)
-    target_sources(FreeRTOS::Timers INTERFACE "${FreeRTOS_SOURCE_DIR}/timers.c")
-    target_link_libraries(FreeRTOS::Timers INTERFACE FreeRTOS)
-endif()
+list(REMOVE_DUPLICATES FreeRTOS_FIND_COMPONENTS)
+list(REMOVE_DUPLICATES FreeRTOS_FIND_COMPONENTS_PORTS)
+list(REMOVE_DUPLICATES FreeRTOS_FIND_COMPONENTS_FAMILIES)
 
-foreach(HEAP ${FreeRTOS_HEAPS})
-    if(NOT (TARGET FreeRTOS::Heap::${HEAP}))
-        add_library(FreeRTOS::Heap::${HEAP} INTERFACE IMPORTED)
-        target_sources(FreeRTOS::Heap::${HEAP} INTERFACE "${FreeRTOS_SOURCE_DIR}/portable/MemMang/heap_${HEAP}.c")
-        target_link_libraries(FreeRTOS::Heap::${HEAP} INTERFACE FreeRTOS)
-    endif()
-endforeach()
+set(FreeRTOS_HEAPS 1 2 3 4 5)
 
-foreach(PORT ${FreeRTOS_FIND_COMPONENTS})
-    find_path(FreeRTOS_${PORT}_PATH
-        NAMES portmacro.h
+macro(stm32_find_freertos FreeRTOS_NAMESPACE FREERTOS_PATH)
+    find_path(FreeRTOS_COMMON_INCLUDE
+        NAMES FreeRTOS.h
         PATHS "${FREERTOS_PATH}" "${FREERTOS_PATH}/FreeRTOS" 
         PATH_SUFFIXES
             "portable/GCC/${PORT}/r0p1"
@@ -101,22 +88,137 @@ foreach(PORT ${FreeRTOS_FIND_COMPONENTS})
         PATHS "${FreeRTOS_${PORT}_PATH}"
         NO_DEFAULT_PATH
     )
-    if(NOT (TARGET FreeRTOS::${PORT}))
-        add_library(FreeRTOS::${PORT} INTERFACE IMPORTED)
-        target_link_libraries(FreeRTOS::${PORT} INTERFACE FreeRTOS)
-        target_sources(FreeRTOS::${PORT} INTERFACE "${FreeRTOS_${PORT}_SOURCE}")
-        target_include_directories(FreeRTOS::${PORT} INTERFACE "${FreeRTOS_${PORT}_PATH}")
+    if(NOT (TARGET FreeRTOS))
+        add_library(FreeRTOS INTERFACE IMPORTED)
+        target_sources(FreeRTOS INTERFACE 
+            "${FreeRTOS_SOURCE_DIR}/tasks.c"
+            "${FreeRTOS_SOURCE_DIR}/list.c"
+            "${FreeRTOS_SOURCE_DIR}/queue.c"
+        )
+        target_include_directories(FreeRTOS INTERFACE "${FreeRTOS_COMMON_INCLUDE}")
     endif()
-    
-    if(FreeRTOS_${PORT}_PATH AND 
-       FreeRTOS_${PORT}_SOURCE AND 
-       FreeRTOS_COMMON_INCLUDE AND
-       FreeRTOS_SOURCE_DIR)
-       set(FreeRTOS_${PORT}_FOUND TRUE)
-    else()
-       set(FreeRTOS_${PORT}_FOUND FALSE)
+
+    if(NOT (TARGET ${FreeRTOS_NAMESPACE}::Coroutine))
+        add_library(${FreeRTOS_NAMESPACE}::Coroutine INTERFACE IMPORTED)
+        target_sources(${FreeRTOS_NAMESPACE}::Coroutine INTERFACE "${FreeRTOS_SOURCE_DIR}/croutine.c")
+        target_link_libraries(${FreeRTOS_NAMESPACE}::Coroutine INTERFACE FreeRTOS)
     endif()
-endforeach()
+
+    if(NOT (TARGET ${FreeRTOS_NAMESPACE}::EventGroups))
+        add_library(${FreeRTOS_NAMESPACE}::EventGroups INTERFACE IMPORTED)
+        target_sources(${FreeRTOS_NAMESPACE}::EventGroups INTERFACE "${FreeRTOS_SOURCE_DIR}/event_groups.c")
+        target_link_libraries(${FreeRTOS_NAMESPACE}::EventGroups INTERFACE FreeRTOS)
+    endif()
+
+    if(NOT (TARGET ${FreeRTOS_NAMESPACE}::StreamBuffer))
+        add_library(${FreeRTOS_NAMESPACE}::StreamBuffer INTERFACE IMPORTED)
+        target_sources(${FreeRTOS_NAMESPACE}::StreamBuffer INTERFACE "${FreeRTOS_SOURCE_DIR}/stream_buffer.c")
+        target_link_libraries(${FreeRTOS_NAMESPACE}::StreamBuffer INTERFACE FreeRTOS)
+    endif()
+
+    if(NOT (TARGET ${FreeRTOS_NAMESPACE}::Timers))
+        add_library(${FreeRTOS_NAMESPACE}::Timers INTERFACE IMPORTED)
+        target_sources(${FreeRTOS_NAMESPACE}::Timers INTERFACE "${FreeRTOS_SOURCE_DIR}/timers.c")
+        target_link_libraries(${FreeRTOS_NAMESPACE}::Timers INTERFACE FreeRTOS)
+    endif()
+
+    foreach(HEAP ${FreeRTOS_HEAPS})
+        if(NOT (TARGET ${FreeRTOS_NAMESPACE}::Heap::${HEAP}))
+            add_library(${FreeRTOS_NAMESPACE}::Heap::${HEAP} INTERFACE IMPORTED)
+            target_sources(${FreeRTOS_NAMESPACE}::Heap::${HEAP} INTERFACE "${FreeRTOS_SOURCE_DIR}/portable/MemMang/heap_${HEAP}.c")
+            target_link_libraries(${FreeRTOS_NAMESPACE}::Heap::${HEAP} INTERFACE FreeRTOS)
+        endif()
+    endforeach()
+
+    foreach(PORT ${FreeRTOS_FIND_COMPONENTS_PORTS})
+        find_path(FreeRTOS_${PORT}_PATH
+            NAMES portmacro.h
+            PATHS "${FREERTOS_PATH}" "${FREERTOS_PATH}/FreeRTOS" 
+            PATH_SUFFIXES "Source/portable/GCC/${PORT}"  "Source/portable/GCC/${PORT}/r0p1"
+            NO_DEFAULT_PATH
+        )
+        list(APPEND FreeRTOS_INCLUDE_DIRS "${FreeRTOS_${PORT}_PATH}")
+        
+        find_file(FreeRTOS_${PORT}_SOURCE
+            NAMES port.c
+            PATHS "${FreeRTOS_${PORT}_PATH}"
+            NO_DEFAULT_PATH
+        )
+        if(NOT (TARGET ${FreeRTOS_NAMESPACE}::${PORT}))
+            add_library(${FreeRTOS_NAMESPACE}::${PORT} INTERFACE IMPORTED)
+            target_link_libraries(${FreeRTOS_NAMESPACE}::${PORT} INTERFACE FreeRTOS)
+            target_sources(${FreeRTOS_NAMESPACE}::${PORT} INTERFACE "${FreeRTOS_${PORT}_SOURCE}")
+            target_include_directories(${FreeRTOS_NAMESPACE}::${PORT} INTERFACE "${FreeRTOS_${PORT}_PATH}")
+        endif()
+        
+        if(FreeRTOS_${PORT}_PATH AND 
+           FreeRTOS_${PORT}_SOURCE AND 
+           FreeRTOS_COMMON_INCLUDE AND
+           FreeRTOS_SOURCE_DIR)
+           set(FreeRTOS_${PORT}_FOUND TRUE)
+        else()
+           set(FreeRTOS_${PORT}_FOUND FALSE)
+        endif()
+    endforeach()
+endmacro()
+
+if(NOT FreeRTOS_FIND_COMPONENTS_FAMILIES)
+    if(NOT FREERTOS_PATH)
+        set(FREERTOS_PATH /opt/FreeRTOS CACHE PATH "Path to FreeRTOS")
+        message(STATUS "No FREERTOS_PATH specified using default: ${FREERTOS_PATH}")
+    endif()
+    stm32_find_freertos(FreeRTOS ${FREERTOS_PATH})
+else()
+    message(STATUS "Search for FreeRTOS families: ${FreeRTOS_FIND_COMPONENTS_FAMILIES}")
+    message(STATUS "Search for FreeRTOS ports: ${FreeRTOS_FIND_COMPONENTS_PORTS}")
+
+    foreach(COMP ${FreeRTOS_FIND_COMPONENTS_FAMILIES})
+        string(TOLOWER ${COMP} COMP_L)
+        string(TOUPPER ${COMP} COMP)
+        
+        string(REGEX MATCH "^STM32([A-Z][0-9])([0-9A-Z][0-9][A-Z][0-9A-Z])?_?(M[47])?.*$" COMP ${COMP})
+        
+        if((NOT CMAKE_MATCH_1) AND (NOT CMAKE_MATCH_2))
+            message(FATAL_ERROR "Unknown FreeRTOS component: ${COMP}")
+        endif()
+        
+        if(CMAKE_MATCH_2)
+            set(FAMILY ${CMAKE_MATCH_1})
+            set(DEVICES "${CMAKE_MATCH_1}${CMAKE_MATCH_2}")
+        else()
+            set(FAMILY ${CMAKE_MATCH_1})
+            stm32_get_devices_by_family(DEVICES FAMILY ${FAMILY} CORE ${CORE})
+        endif()
+        
+        if(CMAKE_MATCH_3)
+            set(CORE ${CMAKE_MATCH_3})
+            set(CORE_C "::${CORE}")
+            set(CORE_U "_${CORE}")
+        else()
+            unset(CORE)
+            unset(CORE_C)
+            unset(CORE_U)
+        endif()
+        
+        string(TOLOWER ${FAMILY} FAMILY_L)
+        if(NOT STM32_CUBE_${FAMILY}_PATH)
+            set(STM32_CUBE_${FAMILY}_PATH /opt/STM32Cube${FAMILY} CACHE PATH "Path to STM32Cube${FAMILY}")
+            message(STATUS "Did not specify STM32_CMSIS_${FAMILY}_PATH, using default STM32_CUBE_${FAMILY}_PATH: ${STM32_CUBE_${FAMILY}_PATH}")
+        endif()
+        
+        stm32_find_freertos(FreeRTOS::STM32::${FAMILY}${CORE_C} ${STM32_CUBE_${FAMILY}_PATH}/Middlewares/Third_Party/FreeRTOS)
+        foreach(PORT_COMP ${FreeRTOS_FIND_COMPONENTS_PORTS})
+            if(FreeRTOS_${PORT_COMP}_PATH AND 
+               FreeRTOS_${PORT_COMP}_SOURCE AND 
+               FreeRTOS_COMMON_INCLUDE AND
+               FreeRTOS_SOURCE_DIR)
+               set(FreeRTOS_${COMP}_FOUND TRUE)
+            else()
+               set(FreeRTOS_${COMP}_FOUND FALSE)
+            endif()
+        endforeach()
+    endforeach()
+endif()
 
 include(FindPackageHandleStandardArgs)
 find_package_handle_standard_args(FreeRTOS