• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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``. By default,
247   we assume this repository will be named ``@hal_driver``, but this can be
248   overriden with a label flag (discussed below).
249*  ``cmsis_device_{family}`` (e.g., `CMSIS device repo for the F4 family
250   <https://github.com/STMicroelectronics/cmsis_device_f4>`_). We provide a
251   Bazel build file which works for any family at
252   ``@pigweed//third_party/stm32cube/cmsis_device.BUILD.bazel``. By default, we
253   assume this repository will be named ``@cmsis_device``, but this can be
254   overriden with a label flag (discussed below).
255*  ``cmsis_core``, at https://github.com/STMicroelectronics/cmsis_core. We
256   provide a Bazel build file for it at
257   ``@pigweed//third_party/stm32cube/cmsis_core.BUILD.bazel``. By
258   default, we assume this repository will be named ``@cmsis_core``, but this
259   can be overriden with a label flag (discussed below).
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 configuration for your embedded target platforms.
274    Currently, the best way to do this is via a `bazelrc config
275    <https://bazel.build/run/bazelrc#config>`_, which would look like this:
276
277    .. code-block::
278
279       build:stm32f429i --platforms=//targets/stm32f429i_disc1_stm32cube:platform
280       build:stm32f429i --@pigweed//third_party/stm32cube:hal_driver=@stm32f4xx_hal_driver//:hal_driver
281       build:stm32f429i --@stm32f4xx_hal_driver//:cmsis_device=@cmsis_device_f4//:cmsis_device
282       build:stm32f429i --@stm32f4xx_hal_driver//:cmsis_init=@cmsis_device_f4//:default_cmsis_init
283
284    However, once `platform-based flags
285    <https://github.com/bazelbuild/proposals/blob/main/designs/2023-06-08-platform-based-flags.md>`_
286    are implemented in Bazel, it will be possible to set these flags directly
287    in the platform definition.
288
289.. [#] Although CMSIS core is shared by all MCU families, different CMSIS
290   device repositories may not be compatible with the same version of CMSIS
291   core. In this case, you may need to use separate versions of CMSIS core,
292   too.
293
294Defines
295=======
296
297``STM32CUBE_HEADER``
298--------------------
299Upstream Pigweed modules that depend on the STM32Cube HAL, like
300:ref:`module-pw_sys_io_stm32cube`, include the HAL through the family-agnostic
301header ``stm32cube/stm32cube.h``. This header expects the family to be set
302through a define of ``STM32CUBE_HEADER``. So, to use these Pigweed modules, you
303need to set that define to the correct value (e.g., ``\"stm32f4xx.h\"``; note
304the backslashes) as part of your build. This is most conveniently done through
305``copts`` associated with the target platform.
306
307.. _module-pw_stm32cube_build-bazel-label-flags:
308
309Label flags
310===========
311Required
312--------
313``@hal_driver//:hal_config``
314^^^^^^^^^^^^^^^^^^^^^^^^^^^^
315Points to the ``cc_library`` target providing a header with the HAL
316configuration. Note that this header needs an appropriate, family-specific name
317(e.g., ``stm32f4xx_hal_conf.h`` for the F4 family).
318
319Optional
320--------
321These label flags can be used to further customize the behavior of STM32Cube.
322
323``//third_party/stm32cube:hal_driver``
324^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
325This label_flag introduces a layer of indirection useful when building a
326project that requires more than one STM32Cube package (see
327:ref:`module-pw_stm32cube_build-bazel-multifamily`). It should point to the
328repository containing the HAL driver.
329
330The default value is ``@hal_driver``.
331
332``@cmsis_device//:cmsis_core``
333^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
334This label flag should point to the repository containing the CMSIS core build
335target.
336
337The default value is ``@cmsis_core``.
338
339``@hal_driver//:cmsis_device``
340^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
341This label flag should point to the repository containing the CMSIS device
342build target.
343
344The default value is ``@cmsis_device``.
345
346``@hal_driver//:cmsis_init``
347^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
348This label flag should point to the CMSIS initialization code. By default it
349points to the ``system_{family}.c`` template provided in the CMSIS device
350repository.
351
352``@hal_driver//:timebase``
353^^^^^^^^^^^^^^^^^^^^^^^^^^
354This label flag should point to a ``cc_library`` providing a timebase
355implementation. By default it points to the template included with STM's HAL
356repository.
357