• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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