third_party/freertos: Add CMake support

Change-Id: I9d64e933e79339c65d201ef5f1326d5483f5647e
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/79721
Pigweed-Auto-Submit: Ewout van Bekkum <ewout@google.com>
Reviewed-by: Wyatt Hepler <hepler@google.com>
Commit-Queue: Auto-Submit <auto-submit@pigweed.google.com.iam.gserviceaccount.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6499f02..b33e59e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -75,6 +75,7 @@
 add_subdirectory(pw_varint EXCLUDE_FROM_ALL)
 
 add_subdirectory(third_party/nanopb EXCLUDE_FROM_ALL)
+add_subdirectory(third_party/freertos EXCLUDE_FROM_ALL)
 
 if(NOT ZEPHYR_PIGWEED_MODULE_DIR)
   add_subdirectory(targets/host EXCLUDE_FROM_ALL)
diff --git a/third_party/freertos/CMakeLists.txt b/third_party/freertos/CMakeLists.txt
new file mode 100644
index 0000000..d47965e
--- /dev/null
+++ b/third_party/freertos/CMakeLists.txt
@@ -0,0 +1,132 @@
+# Copyright 2022 The Pigweed Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+#     https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+include($ENV{PW_ROOT}/pw_build/pigweed.cmake)
+
+set(dir_pw_third_party_freertos "" CACHE PATH
+    "Path to the FreeRTOS installation's Source directory. \
+     If set, pw_third_party.freertos is provided")
+set(pw_third_party_freertos_CONFIG "" CACHE STRING
+    "The CMake target which provides the FreeRTOS config header")
+set(pw_third_party_freertos_PORT "" CACHE STRING
+    "The CMake target which provides the port specific includes and sources")
+option(pw_third_party_freertos_DISABLE_TASKS_STATICS
+       "Whether to disable statics inside of tasks.c")
+
+if("${dir_pw_third_party_freertos}" STREQUAL "")
+  return()
+elseif("${pw_third_party_freertos_PORT}" STREQUAL "")
+  message(FATAL_ERROR "FreeRTOS is being used, but "
+          "pw_third_party_freertos_PORT is not set.")
+elseif("${pw_third_party_freertos_CONFIG}" STREQUAL "")
+  message(FATAL_ERROR "FreeRTOS is being used, but "
+          "pw_third_party_freertos_CONFIG is not set.")
+endif()
+
+pw_add_module_library(pw_third_party.freertos.disable_warnings
+  PUBLIC_COMPILE_OPTIONS
+    -Wno-unused-parameter
+    -Wno-cast-qual
+)
+
+pw_add_module_library(pw_third_party.freertos
+  HEADERS
+    ${dir_pw_third_party_freertos}/include/FreeRTOS.h
+    ${dir_pw_third_party_freertos}/include/StackMacros.h
+    ${dir_pw_third_party_freertos}/include/croutine.h
+    ${dir_pw_third_party_freertos}/include/deprecated_definitions.h
+    ${dir_pw_third_party_freertos}/include/event_groups.h
+    ${dir_pw_third_party_freertos}/include/list.h
+    ${dir_pw_third_party_freertos}/include/message_buffer.h
+    ${dir_pw_third_party_freertos}/include/mpu_prototypes.h
+    ${dir_pw_third_party_freertos}/include/mpu_wrappers.h
+    ${dir_pw_third_party_freertos}/include/portable.h
+    ${dir_pw_third_party_freertos}/include/projdefs.h
+    ${dir_pw_third_party_freertos}/include/queue.h
+    ${dir_pw_third_party_freertos}/include/semphr.h
+    ${dir_pw_third_party_freertos}/include/stack_macros.h
+    ${dir_pw_third_party_freertos}/include/stream_buffer.h
+    ${dir_pw_third_party_freertos}/include/task.h
+    ${dir_pw_third_party_freertos}/include/timers.h
+  PUBLIC_INCLUDES
+    ${dir_pw_third_party_freertos}/include
+  PUBLIC_DEPS
+    ${pw_third_party_freertos_CONFIG}
+    ${pw_third_party_freertos_PORT}
+  SOURCES
+    ${dir_pw_third_party_freertos}/croutine.c
+    ${dir_pw_third_party_freertos}/event_groups.c
+    ${dir_pw_third_party_freertos}/list.c
+    ${dir_pw_third_party_freertos}/queue.c
+    ${dir_pw_third_party_freertos}/stream_buffer.c
+    ${dir_pw_third_party_freertos}/timers.c
+  PRIVATE_DEPS
+    pw_third_party.freertos.freertos_tasks
+    pw_third_party.freertos.disable_warnings
+)
+
+if(pw_third_party_freertos_DISABLE_TASKS_STATICS)
+  set(disable_tasks_statics "static=" "PW_THIRD_PARTY_FREERTOS_NO_STATICS=1")
+endif()
+pw_add_module_library(pw_third_party.freertos.freertos_tasks
+  SOURCES
+    ${dir_pw_third_party_freertos}/tasks.c
+  PRIVATE_DEPS
+    ${pw_third_party_freertos_CONFIG}
+    ${pw_third_party_freertos_PORT}
+    pw_third_party.freertos.disable_warnings
+  PRIVATE_INCLUDES
+    ${dir_pw_third_party_freertos}/include
+  PRIVATE_DEFINES
+    ${disable_tasks_statics}
+)
+
+# ARM CM4F port of FreeRTOS.
+pw_add_module_library(pw_third_party.freertos.arm_cm4f
+  HEADERS
+    ${dir_pw_third_party_freertos}/portable/GCC/ARM_CM4F/portmacro.h
+  PUBLIC_DEPS
+    ${pw_third_party_freertos_CONFIG}
+  PUBLIC_INCLUDES
+    ${dir_pw_third_party_freertos}/include
+    ${dir_pw_third_party_freertos}/portable/GCC/ARM_CM4F
+  SOURCES
+    ${dir_pw_third_party_freertos}/portable/GCC/ARM_CM4F/port.c
+  PRIVATE_DEPS
+    pw_third_party.freertos.disable_warnings
+)
+
+# ARM CM33F port of FreeRTOS.
+pw_add_module_library(pw_third_party.freertos.arm_cm33f
+  HEADERS
+    ${dir_pw_third_party_freertos}/portable/GCC/ARM_CM33F/portmacro.h
+  PUBLIC_DEPS
+    ${pw_third_party_freertos_CONFIG}
+  PUBLIC_INCLUDES
+    ${dir_pw_third_party_freertos}/include
+    ${dir_pw_third_party_freertos}/portable/GCC/ARM_CM33F
+  SOURCES
+    ${dir_pw_third_party_freertos}/portable/GCC/ARM_CM33F/port.c
+  PRIVATE_DEPS
+    pw_third_party.freertos.disable_warnings
+)
+
+pw_add_module_library(pw_third_party.freertos.config_assert
+  HEADERS
+    public/pw_third_party/freertos/config_assert.h
+  PUBLIC_INCLUDES
+    public
+  PUBLIC_DEPS
+    pw_assert
+)
diff --git a/third_party/freertos/docs.rst b/third_party/freertos/docs.rst
index e90d87c..e7d9050 100644
--- a/third_party/freertos/docs.rst
+++ b/third_party/freertos/docs.rst
@@ -7,12 +7,14 @@
 The ``$dir_pw_third_party/freertos/`` module contains various helpers to use
 FreeRTOS, including Pigweed backend modules which depend on FreeRTOS.
 
-----------------
-GN Build Support
-----------------
-This module provides support to compile FreeRTOS with GN. This is required when
-compiling backends modules for FreeRTOS.
+-------------
+Build Support
+-------------
+This module provides support to compile FreeRTOS with GN and CMake. This is
+required when compiling backends modules for FreeRTOS.
 
+GN
+==
 In order to use this you are expected to configure the following variables from
 ``$dir_pw_third_party/freertos:freertos.gni``:
 
@@ -26,6 +28,19 @@
 After this is done a ``pw_source_set`` for the FreeRTOS library is created at
 ``$dir_pw_third_party/freertos``.
 
+CMake
+=====
+In order to use this you are expected to set the following variables from
+``third_party/freertos/CMakeLists.txt``:
+
+#. Set the GN ``dir_pw_third_party_freertos`` to the path of the FreeRTOS
+   installation.
+#. Set ``pw_third_party_freertos_CONFIG`` to a library target which provides
+   the FreeRTOS config header.
+#. Set ``pw_third_party_freertos_PORT`` to a library target which provides
+   the FreeRTOS port specific includes and sources.
+
+
 .. _third_party-freertos_disable_task_statics:
 
 Linking against FreeRTOS kernel's static internals
@@ -35,10 +50,12 @@
 to enable use of things like pw_thread_freertos/util.h's ``ForEachThread``.
 
 To facilitate this, Pigweed offers an opt-in option which can be enabled by
-configuring the following GN
-through ``pw_third_party_freertos_DISABLE_TASKS_STATICS = true``. This redefines
-``static`` to nothing for the ``Source/tasks.c`` FreeRTOS source file
-when building through ``$dir_pw_third_party/freertos``.
+configuring GN through
+``pw_third_party_freertos_DISABLE_TASKS_STATICS = true`` or CMake through
+``set(pw_third_party_freertos_DISABLE_TASKS_STATICS ON CACHE BOOL "" FORCE)``.
+This redefines ``static`` to nothing for the ``Source/tasks.c`` FreeRTOS source
+file when building through ``$dir_pw_third_party/freertos`` in GN and through
+``pw_third_party.freertos`` in CMake.
 
 .. attention:: If you use this, make sure that your FreeRTOSConfig.h and port
   does not rely on any statics inside of tasks.c. For example, you cannot use