1.. _module-pw_stm32cube_build: 2 3================== 4pw_stm32cube_build 5================== 6The ``pw_stm32cube_build`` module provides helper utilities for building a 7target with the stm32cube HAL and/or the stm32cube initialization code. 8 9The actual GN build files and headers live in ``third_party/stm32cube`` but 10are documented here. The rationale for keeping the build files in `third_party` 11is that code depending on stm32cube can clearly see that their dependency is on 12third party, not pigweed code. 13 14.. _module-pw_stm32cube_build-components: 15 16------------------------ 17STM32Cube MCU Components 18------------------------ 19Each stm32 product family (ex. F4, L5, etc.) has its own stm32cube libraries. 20This integration depends on ST's 3 core `MCU Components`_ instead of their 21monolithic `MCU Package`. The components are the hal_driver, cmsis_core, and 22cmsis_device. All of these repos exist on `ST's GitHub page`_. Compatible 23version tags are specified on the ``README.md`` of each MCU component. 24 25To use Pigweed's STM32Cube integration, you will need to acquire the three 26components. The details are build-system dependent. 27 28-------- 29GN build 30-------- 31The primary ``pw_source_set`` for this integration is 32``$dir_pw_third_party/stm32cube:stm32cube``. This source set includes all of 33the HAL, init code, and templates, depending on the value of the `GN args`_. 34 35Directory setup 36=============== 37Within a single directory, the following directory/file names are required. 38 39=============== ============================================= 40Dir/File Name Description 41=============== ============================================= 42hal_driver/ checkout of ``stm32{family}xx_hal_driver`` 43cmsis_device/ checkout of ``cmsis_device_{family}`` 44cmsis_core/ checkout of ``cmsis_core`` 45files.txt list of files generated by `gen_file_list`_ 46=============== ============================================= 47 48pw_package 49---------- 50The stm32cube directory can alternatively be setup using ``pw_package``. This 51will automatically download compatible repos into the expected folders and 52generate the ``files.txt``. 53 54.. code-block:: bash 55 56 pw package install stm32cube_{family} 57 58Headers 59======= 60``$dir_pw_third_party/stm32cube:stm32cube`` contains the following primary 61headers that external targets / applications would care about. 62 63``{family}.h`` 64-------------- 65ex. ``stm32f4xx.h``, ``stm32l5xx.h`` 66 67This is the primary HAL header provided by stm32cube. It includes the entire 68HAL and all product specific defines. 69 70``stm32cube/stm32cube.h`` 71------------------------- 72This is a convenience define provided by this integration. It simply includes 73``{family}.h``. 74 75This is useful because there is a lot of commonality between the HAL's of the 76different stm32 families. Although the API's are not guaranteed to be 77compatible, many basic API's often are (ex. GPIO, UART, etc.). This common 78header allows for stm32 family agnostic modules (ex. ``pw_sys_io_stm32``, which 79could work with most, if not all families). 80 81``stm32cube/init.h`` 82-------------------- 83As described in the inject_init_ section, if you decide to use the built in 84init functionality, a pre main init function call, ``pw_stm32cube_Init()``, is 85injected into ST's startup scripts. 86 87This header contains the ``pw_stm32cube_Init()`` function declaration. It 88should be included and implemented by target init code. 89 90GN args 91======= 92The stm32cube GN build arguments are defined in 93``$dir_pw_third_party/stm32cube/stm32cube.gni``. 94 95``dir_pw_third_party_stm32cube_xx`` 96----------------------------------- 97These should be set to point to the stm32cube directory for each family that 98you need to build for. These are optional to set and are only provided for 99convenience if you need to build for multiple families in the same project. 100 101``dir_pw_third_party_stm32cube`` 102----------------------------------- 103This needs to point to the stm32cube directory for the current build. 104 105For multi target projects, the standard practice to set this for each target: 106 107.. code-block:: text 108 109 dir_pw_third_party_stm32cube = dir_pw_third_party_stm32cube_f4 110 111 112``pw_third_party_stm32cube_PRODUCT`` 113------------------------------------ 114The product specified in as much detail as possible. 115ex. ``stm32f429zit``, ``stm32l552ze``, ``stm32f207zg``, etc. 116 117``pw_third_party_stm32cube_CONFIG`` 118------------------------------------ 119The pw_source_set that provides ``stm32{family}xx_hal_conf.h``. The default 120uses the in-tree ``stm32{family}xx_hal_conf_template.h``. 121 122``pw_third_party_stm32cube_TIMEBASE`` 123------------------------------------- 124The pw_source_set containing the timebase. The default uses the in-tree 125``stm32{family}xx_hal_timebase_tim_template.c``. 126 127``pw_third_party_stm32cube_CMSIS_INIT`` 128--------------------------------------- 129The pw_source_set containing the cmsis init logic. The default uses the in-tree 130``system_stm32{family}xx.c``. 131 132``pw_third_party_stm32cube_CORE_INIT`` 133-------------------------------------- 134pw_source_set containing the core initialization logic. This normally includes 135a ``startup_stm32{...}.s`` + a dependent ``pw_linker_script``. The default 136``core_init_template`` uses the upstream startup and linker script matching 137``pw_third_party_stm32cube_PRODUCT``. If set to "", you must provide your own 138linker/startup logic somewhere else in the build. 139 140----------------- 141stm32cube_builder 142----------------- 143``stm32cube_builder`` is utility that contains the backend scripts used by 144``pw_package/stm32cube`` and the GN build scripts in ``third_party/stm32cube`` 145to interact with the stm32cube repos. You should only need to interact with 146``stm32cube_builder`` directly if you are doing something custom, like 147using git submodules instead of pw_package, forking the stm32cube libraries, 148interfacing with a different build system, or using your own init. 149 150gen_file_list 151============= 152Build systems like GN are unable to depend on arbitrary directories. Instead, 153they must have dependencies on specific files. The HAL for each stm32 product 154family has different filenames, so ``files.txt`` was created as a workaround. 155``files.txt`` is a basic list of all the files in the stm32cube directory with 156relavent file extensions. The build system only directly depends on this list, 157which must be updated everytime the underlying repos are updated. 158 159This command will generate ``files.txt`` for correctly structured stm32cube 160directories. 161 162.. code-block:: bash 163 164 stm32cube_builder gen_file_list /path/to/stm32cube_dir 165 166find_files 167========== 168Within each stm32 family, there are specific products. Although most of the 169HAL is common between products, the init code is almost always different. 170``find_files`` looks for all of the files relevant to a particular product 171within a stm32cube directory. 172 173The product string should be specified in as much detail as possible because 174there are sometimes different defines or init code for submembers of products. 175 176Ex. ``stm32f412cx``, ``stm32f412rx``, ``stm32f412vx``, and ``stm32f412zx`` all 177have different init logic, while all ``stm32f439xx`` have the same init. 178 179``find_files`` only ever looks for init (linker + startup scripts) if the 180``--init`` flag is provided. 181 182The output is currently only provided in the GN 'scope' format to stdout. 183The following variables are output: ``family``, ``product_define``, 184``sources``, ``headers``, ``include_dirs``, and the following three if 185``--init`` is specified: ``startup``, ``gcc_linker``, ``iar_linker``. 186 187.. code-block:: bash 188 189 stm32cube_builder find_files /path/to/stm32cube_dir stm32{family}{product} [--init] 190 191inject_init 192============= 193ST provides init assembly files for every product in ``cmsis_device``. This is 194helpful for getting up and running quickly, but they directly call into 195``main()`` before initializing the hardware / peripherals. This is because they 196expect to do that initialization in ``main()``, then call into the user 197application. Upstream Pigweed unit tests expect at least ``sys_io`` to be 198initialized before ``main()`` is called. 199 200This command injects a call to ``pw_stm32cube_Init()`` immediately before the 201call to ``main()``. This function should be implemented by the target to do 202whatever init is necessary (hal init, sys_io init, clock configuration, etc.) 203 204``inject_init`` takes in an ST assembly script and outputs the same script with 205the pre main init call. The output is printed to stdout, or to the specified 206``--out-startup-path``. 207 208.. code-block:: bash 209 210 stm32cube_builder inject_init /path/to/startup.s [--out-startup-path /path/to/new_startup.s] 211 212icf_to_ld 213========= 214Pigweed primarily uses GCC for its Cortex-M builds. However, ST only provides 215IAR linker scripts in ``cmsis_device`` for most product families. This script 216converts from ST's IAR linker script format (.icf) to a basic GCC linker 217script (.ld). This is a very basic converter that only works with exactly how 218ST currently formats their .icf files. 219 220The output .ld files only contain ``RAM`` and ``FLASH`` sections. Anything more 221complicated will require hand customized .ld scripts. Output is printed to 222stdout or the specified ``--ld-path``. 223 224.. code-block:: bash 225 226 stm32cube_builder inject_init /path/to/iar_linker.icf [--ld-path /path/to/gcc_linker.ld] 227 228.. _`MCU Components`: https://github.com/STMicroelectronics/STM32Cube_MCU_Overall_Offer#stm32cube-mcu-components 229.. _`ST's GitHub page`: https://github.com/STMicroelectronics 230 231.. _module-pw_stm32cube_build-bazel: 232 233----------- 234Bazel build 235----------- 236 237External dependencies 238===================== 239As discussed above in :ref:`module-pw_stm32cube_build-components`, you need the 240three STM32Cube Components for your MCU family to use Pigweed's STM32Cube 241integration. You need to add the following git repositories to your workspace: 242 243* ``stm32{family}xx_hal_driver`` (e.g., `HAL driver repo for the F4 family 244 <https://github.com/STMicroelectronics/stm32f4xx_hal_driver/>`_). We provide 245 a Bazel build file which works for any family at 246 ``@pigweed//third_party/stm32cube/stm32_hal_driver.BUILD.bazel``. Below, 247 we'll refer to this repository as ``@hal_driver``. 248* ``cmsis_device_{family}`` (e.g., `CMSIS device repo for the F4 family 249 <https://github.com/STMicroelectronics/cmsis_device_f4>`_). We provide a 250 Bazel build file which works for any family at 251 ``@pigweed//third_party/stm32cube/cmsis_device.BUILD.bazel``. Below, we'll 252 refer to this repository as ``@cmsis_device``. 253* ``cmsis_core``, at https://github.com/STMicroelectronics/cmsis_core. We 254 provide a Bazel build file for it at 255 ``@pigweed//third_party/stm32cube/cmsis_core.BUILD.bazel``. Below, we'll 256 refer to this repository as ``@cmsis_core``. 257 258.. _module-pw_stm32cube_build-bazel-multifamily: 259 260Building for more than one MCU family 261------------------------------------- 262Different MCU families require different HAL driver and CMSIS device packages 263from STM. So, if your project builds firmware for more than one MCU family, you 264will need to configure separate sets of the three [#]_ STM repositories for each MCU 265family. To do so, 266 2671. Add the appropriate repositories to your WORKSPACE under different names, 268 eg. ``@stm32f4xx_hal_driver`` and ``@stm32h7xx_hal_driver``. 2692. Set the corresponding :ref:`module-pw_stm32cube_build-bazel-label-flags` as 270 part of the platform definition for your embedded target platforms. 271 272.. code-block:: text 273 274 platform( 275 name = "...", 276 ... 277 flags = flags_from_dict({ 278 ... 279 "@cmsis_core//:cc_defines": ":<your cc_defines target>", 280 "@stm32f4xx_hal_driver//:hal_config": "//targets/stm32f429i_disc1_stm32cube:hal_config", 281 "@pigweed//third_party/stm32cube:hal_driver": "@stm32f4xx_hal_driver//:hal_driver", 282 "@stm32f4xx_hal_driver//:cmsis_device": "@cmsis_device_f4//:cmsis_device", 283 "@stm32f4xx_hal_driver//:cmsis_init": "@cmsis_device_f4//:default_cmsis_init", 284 "@cmsis_device_f4//:cmsis_core": "@cmsis_core", 285 }), 286 ) 287 288.. [#] Although CMSIS core is shared by all MCU families, different CMSIS 289 device repositories may not be compatible with the same version of CMSIS 290 core. In this case, you may need to use separate versions of CMSIS core, 291 too. 292 293Defines 294======= 295 296``STM32CUBE_HEADER`` 297-------------------- 298Upstream Pigweed modules that depend on the STM32Cube HAL, like 299:ref:`module-pw_sys_io_stm32cube`, include the HAL through the family-agnostic 300header ``stm32cube/stm32cube.h``. This header expects the family to be set 301through a define of ``STM32CUBE_HEADER``. So, to use these Pigweed modules, you 302need to set that define to the correct value (e.g., ``\"stm32f4xx.h\"``; note 303the backslashes) as part of your build. This is most conveniently done via the 304``defines`` attribute of a ``cc_library`` target which is then set as the 305value of the ``@cmsis_core//:cc_defines`` label flag. 306 307.. _module-pw_stm32cube_build-bazel-label-flags: 308 309Label flags 310=========== 311Required 312-------- 313``//third_party/stm32cube:hal_driver`` 314^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 315This label_flag should point to the repository containing the HAL driver. 316We'll refer to this repository as ``@hal_driver`` below. 317 318``@hal_driver//:hal_config`` 319^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 320Points to the ``cc_library`` target providing a header with the HAL 321configuration. Note that this header needs an appropriate, family-specific name 322(e.g., ``stm32f4xx_hal_conf.h`` for the F4 family). 323 324``@cmsis_core//:cc_defines`` 325^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 326This label flag should point to a `cc_library` target which adds `define` 327entries for `STM32CUBE_HEADER` and the `STM32....` family (e.g. `STM32F429xx`). 328 329``@cmsis_device//:cmsis_core`` 330^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 331This label flag should point to the repository containing the CMSIS core build 332target (``@cmsis_core``). 333 334``@hal_driver//:cmsis_device`` 335^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 336This label flag should point to the repository containing the CMSIS device 337build target. (``@cmsis_device``). 338 339``@hal_driver//:cmsis_init`` 340^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 341This label flag should point to the CMSIS initialization code 342``@cmsis_device://default_cmsis_init``, the ``system_{family}.c`` template 343provided in the CMSIS device repository, is a good starting choice. 344 345Optional 346-------- 347These label flags can be used to further customize the behavior of STM32Cube. 348 349 350``@hal_driver//:timebase`` 351^^^^^^^^^^^^^^^^^^^^^^^^^^ 352This label flag should point to a ``cc_library`` providing a timebase 353implementation. By default it points to the template included with STM's HAL 354repository. 355