Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CMSIS RTOS Feature #253

Merged
merged 4 commits into from
Aug 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 76 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,24 @@ It uses cmake and GCC, along with newlib (libc), STM32Cube. Supports F0 F1 F2 F3
* `fetch-cube` ([examples/fetch-cube](examples/fetch-cube)) - example of using FetchContent for fetching STM32Cube from ST's git.
* `fetch-cmsis-hal` ([examples/fetch-cmsis-hal](examples/fetch-cmsis-hal)) - example of using FetchContent for fetching STM32 CMSIS and HAL from ST's git.
* `blinky` ([examples/blinky](examples/blinky)) - blink led using STM32 HAL library and SysTick.
It will compile a project for the `F4` family by default, but you can also compile for the
`L0` and `F1` family by passing `L0_EXAMPLE=ON` or `F1_EXAMPLE=ON` to the CMake generation call.
It will compile a project for the `F4` family by default, but you can also compile for the
`L0` and `F1` family by passing `BLINKY_L0_EXAMPLE=ON` or `BLINKY_F1_EXAMPLE=ON` to the CMake
generation call.
* `freertos` ([examples/freertos](examples/freertos)) - blink led using STM32 HAL library and FreeRTOS.
You need to specify at least one board by passing `FREERTOS_<BOARD>_EXAMPLE=ON` to CMake.
Currently, the example can be built for the `H743ZI` and `F407VG` board targets.
You can opt to use the FreeRTOS CMSIS implementation provided by the Cube repository by supplying
`USE_CMSIS_RTOS=ON` or `USE_CMSIS_RTOS_V2` to CMake.

# Usage

First of all you need to configure toolchain and library paths using CMake variables. There are
generally three ways to do this:

1. Pass the variables through command line during cmake run with passed to CMake with
1. Pass the variables through command line during cmake run with passed to CMake with
`-D<VAR_NAME>=...`
2. Set the variables inside your `CMakeLists.txt`
3. Pass these variables to CMake by setting them as environmental variables.
3. Pass these variables to CMake by setting them as environmental variables.

The most important set of variables which needs to be set can be found in the following section.

Expand Down Expand Up @@ -206,21 +211,78 @@ stm32-cmake contains additional CMake modules for finding and configuring variou
`FREERTOS_PATH` can be either the path to the whole
[FreeRTOS/FreeRTOS](https://github.com/FreeRTOS/FreeRTOS) github repo, or the path to
FreeRTOS-Kernel (usually located in the subfolder `FreeRTOS` on a downloaded release).
You can supply `FREERTOS_PATH` as an environmental variable as well.
`FREERTOS_PATH` can be supplied as an environmental variable as well.

Typical usage:
It is possible to either use the FreeRTOS kernel provided in the Cube repositories, or a separate
FreeRTOS kernel. The Cube repository also provides the CMSIS RTOS and CMSIS RTOS V2 implementations.
If the CMSIS implementations is used, it is recommended to also use the FreeRTOS sources
provided in the Cube repository because the CMSIS port might be incompatible to newer kernel
versions. The FreeRTOS port to use is specified as a `FreeRTOS` component. A list of available
ports can be found below. If the FreeRTOS sources provided in the Cube repository are used, the
device family also has to be specified as a component for the `FreeRTOS` package.

CMSIS RTOS can be used by specifying a `CMSIS` target and by finding the CMSIS `RTOS` package.
The following section will show a few example configurations for the H7 and F4 family.
You can also find example code for the `H743ZI` and `F407VG` devices in the `examples`
folder.

Typical usage for a H7 device when using the M7 core, using an external kernel without CMSIS
support. The FreeRTOS namespace is set to `FreeRTOS` and the `ARM_CM7` port is used:

```cmake
find_package(CMSIS COMPONENTS STM32H743ZI STM32H7_M7 REQUIRED)
find_package(FreeRTOS ARM_CM7 REQUIRED)
target_link_libraries(${TARGET_NAME} PRIVATE
...
FreeRTOS::ARM_CM7
)
```

Typical usage for a F4 device, using an external kernel without CMSIS support.
The FreeRTOS namespace is set to `FreeRTOS` and the `ARM_CM4F` port is used:

```cmake
find_package(FreeRTOS COMPONENTS ARM_CM4F REQUIRED)
target_link_libraries(... FreeRTOS::ARM_CM4F)
target_link_libraries(${TARGET_NAME} PRIVATE
...
FreeRTOS::ARM_CM4F
)
```

Another typical usage using the FreeRTOS provided in the Cube repository and the CMSIS support.
The FreeRTOS namespace is set to `FreeRTOS::STM32::<FAMILY>`, the `ARM_CM7` port is used and
the device family is specified as a `FreeRTOS` component with `STM32H7`:

```cmake
find_package(CMSIS COMPONENTS STM32H743ZI STM32H7_M7 RTOS REQUIRED)
find_package(FreeRTOS COMPONENTS ARM_CM7 STM32H7 REQUIRED)
target_link_libraries(${TARGET_NAME} PRIVATE
...
FreeRTOS::STM32::H7::M7::ARM_CM7
CMSIS::STM32::H7::M7::RTOS
)
```

The following FreeRTOS ports are supported: `ARM_CM0`, `ARM_CM3`, `ARM_CM4F`, `ARM_CM7`.
The following CMSIS targets are available in general:

* `CMSIS::STM32::<Family>::RTOS`
* `CMSIS::STM32::<Family>::RTOS_V2`

The following additional FreeRTOS targets are available in general to use the FreeRTOS provided
in the Cube repository

* `FreeRTOS::STM32::<Family>`

For the multi-core architectures, both family and core need to be specified like shown in the
example above.

The following FreeRTOS ports are supported in general: `ARM_CM0`, `ARM_CM3`, `ARM_CM4F`, `ARM_CM7`,
`ARM_CM3_MPU`, `ARM_CM4_MPU`, `ARM_CM7_MPU`.

Other FreeRTOS libraries:
Other FreeRTOS libraries, with `FREERTOS_NAMESPACE` being set as specified in the examples above:

* `FreeRTOS::Coroutine` - co-routines (`croutines.c`)
* `FreeRTOS::EventGroups` - event groups (`event_groups.c`)
* `FreeRTOS::StreamBuffer` - stream buffer (`stream_buffer.c`)
* `FreeRTOS::Timers` - timers (`timers.c`)
* `FreeRTOS::Heap::<N>` - heap implementation (`heap_<N>.c`), `<N>`: [1-5]
* `${FREERTOS_NAMESPACE}::Coroutine` - co-routines (`croutines.c`)
* `${FREERTOS_NAMESPACE}::EventGroups` - event groups (`event_groups.c`)
* `${FREERTOS_NAMESPACE}::StreamBuffer` - stream buffer (`stream_buffer.c`)
* `${FREERTOS_NAMESPACE}::Timers` - timers (`timers.c`)
* `${FREERTOS_NAMESPACE}::Heap::<N>` - heap implementation (`heap_<N>.c`), `<N>`: [1-5]
71 changes: 70 additions & 1 deletion cmake/FindCMSIS.cmake
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
set(CMSIS_RTOS RTOS RTOS_V2)

if(NOT CMSIS_FIND_COMPONENTS)
set(CMSIS_FIND_COMPONENTS ${STM32_SUPPORTED_FAMILIES_LONG_NAME})
endif()
Expand All @@ -7,6 +9,35 @@ if(STM32H7 IN_LIST CMSIS_FIND_COMPONENTS)
endif()
list(REMOVE_DUPLICATES CMSIS_FIND_COMPONENTS)

# This section fills the RTOS or family components list
foreach(COMP ${CMSIS_FIND_COMPONENTS})
string(TOLOWER ${COMP} COMP_L)
string(TOUPPER ${COMP} COMP)

# Component is RTOS component
if(${COMP} IN_LIST CMSIS_RTOS)
list(APPEND CMSIS_FIND_COMPONENTS_RTOS ${COMP})
continue()
endif()

# Component is not RTOS component, so check whether it is a family component
string(REGEX MATCH "^STM32([A-Z][0-9])([0-9A-Z][0-9][A-Z][0-9A-Z])?_?(M[47])?.*$" COMP ${COMP})
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a note to myself for #235 #249
Regex will need update at multiple places (not done by automerge).

if(CMAKE_MATCH_1)
list(APPEND CMSIS_FIND_COMPONENTS_FAMILIES ${COMP})
endif()
endforeach()

if(NOT CMSIS_FIND_COMPONENTS_FAMILIES)
set(CMSIS_FIND_COMPONENTS_FAMILIES ${STM32_SUPPORTED_FAMILIES_LONG_NAME})
endif()

if(NOT CMSIS_FIND_COMPONENTS_RTOS)
set(CMSIS_FIND_COMPONENTS_RTOS ${CMSIS_RTOS})
endif()

message(STATUS "Search for CMSIS families: ${CMSIS_FIND_COMPONENTS_FAMILIES}")
message(STATUS "Search for CMSIS RTOS: ${CMSIS_FIND_COMPONENTS_RTOS}")

include(stm32/devices)

function(cmsis_generate_default_linker_script FAMILY DEVICE CORE)
Expand Down Expand Up @@ -41,7 +72,7 @@ function(cmsis_generate_default_linker_script FAMILY DEVICE CORE)
stm32_add_linker_script(CMSIS::STM32::${DEVICE}${CORE_C} INTERFACE "${OUTPUT_LD_FILE}")
endfunction()

foreach(COMP ${CMSIS_FIND_COMPONENTS})
foreach(COMP ${CMSIS_FIND_COMPONENTS_FAMILIES})
string(TOLOWER ${COMP} COMP_L)
string(TOUPPER ${COMP} COMP)

Expand Down Expand Up @@ -176,6 +207,44 @@ foreach(COMP ${CMSIS_FIND_COMPONENTS})
else()
set(CMSIS_${COMP}_FOUND FALSE)
endif()

foreach(RTOS_COMP ${CMSIS_FIND_COMPONENTS_RTOS})
if (${RTOS_COMP} STREQUAL "RTOS_V2")
set(RTOS_COMP_VERSION "2")
else()
unset(RTOS_COMP_VERSION)
endif()

find_path(CMSIS_${FAMILY}${CORE_U}_${RTOS_COMP}_PATH
NAMES "cmsis_os${RTOS_COMP_VERSION}.h"
PATHS "${STM32_CUBE_${FAMILY}_PATH}/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_${RTOS_COMP}"
NO_DEFAULT_PATH
)
if (NOT CMSIS_${FAMILY}${CORE_U}_${RTOS_COMP}_PATH)
continue()
endif()

find_file(CMSIS_${FAMILY}${CORE_U}_${RTOS_COMP}_SOURCE
NAMES "cmsis_os${RTOS_COMP_VERSION}.c"
PATHS "${STM32_CUBE_${FAMILY}_PATH}/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_${RTOS_COMP}"
NO_DEFAULT_PATH
)
if (NOT CMSIS_${FAMILY}${CORE_U}_${RTOS_COMP}_SOURCE)
continue()
endif()

if(NOT (TARGET CMSIS::STM32::${FAMILY}${CORE_C}::${RTOS_COMP}))
add_library(CMSIS::STM32::${FAMILY}${CORE_C}::${RTOS_COMP} INTERFACE IMPORTED)
target_link_libraries(CMSIS::STM32::${FAMILY}${CORE_C}::${RTOS_COMP} INTERFACE CMSIS::STM32::${FAMILY}${CORE_C})
target_include_directories(CMSIS::STM32::${FAMILY}${CORE_C}::${RTOS_COMP} INTERFACE "${CMSIS_${FAMILY}${CORE_U}_${RTOS_COMP}_PATH}")
target_sources(CMSIS::STM32::${FAMILY}${CORE_C}::${RTOS_COMP} INTERFACE "${CMSIS_${FAMILY}${CORE_U}_${RTOS_COMP}_SOURCE}")
endif()

list(APPEND CMSIS_SOURCES "${CMSIS_${FAMILY}${CORE_U}_${RTOS_COMP}_SOURCE}")
list(APPEND CMSIS_INCLUDE_DIRS "${CMSIS_${FAMILY}${CORE_U}_${RTOS_COMP}_PATH}")
set(CMSIS_${RTOS_COMP}_FOUND TRUE)
endforeach()

list(REMOVE_DUPLICATES CMSIS_INCLUDE_DIRS)
list(REMOVE_DUPLICATES CMSIS_SOURCES)
endforeach()
Expand Down
Loading