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