aboutsummaryrefslogtreecommitdiff
path: root/pw_stm32cube_build/docs.rst
blob: 632149536c3f3894f60f4f11fb44c9945203fc5e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
.. _module-pw_stm32cube_build:

------------------
pw_stm32cube_build
------------------

The ``pw_stm32cube_build`` module provides helper utilities for building a
target with the stm32cube HAL and/or the stm32cube initialization code.

The actual GN build files and headers live in ``third_party/stm32cube`` but
are documented here. The rationale for keeping the build files in `third_party`
is that code depending on stm32cube can clearly see that their dependency is on
third party, not pigweed code.

STM32Cube directory setup
=========================
Each stm32 product family (ex. F4, L5, etc.) has its own stm32cube libraries.
This integration depends on ST's 3 core  `MCU Components`_ instead of their
monolithic `MCU Package`. The components are the hal_driver, cmsis_core, and
cmsis_device. All of these repos exist on `ST's GitHub page`_. Compatible
version tags are specified on the ``README.md`` of each MCU component.
Within a single directory, the following directory/file names are required.

=============== =============================================
Dir/File Name     Description
=============== =============================================
hal_driver/       checkout of ``stm32{family}xx_hal_driver``
cmsis_device/     checkout of ``cmsis_device_{family}``
cmsis_core/       checkout of ``cmsis_core``
files.txt         list of files generated by `gen_file_list`_
=============== =============================================

pw_package
----------
The stm32cube directory can alternatively be setup using ``pw_package``. This
will automatically download compatible repos into the expected folders and
generate the ``files.txt``.

.. code-block:: bash

  pw package install stm32cube_{family}

GN build
========
The primary ``pw_source_set`` for this integration is
``$dir_pw_third_party/stm32cube:stm32cube``. This source set includes all of
the HAL, init code, and templates, depending on value of the `GN args`_.

Headers
-------
``$dir_pw_third_party/stm32cube:stm32cube`` contains the following primary
headers that external targets / applications would care about.

``{family}.h``
^^^^^^^^^^^^^^
ex. ``stm32f4xx.h``, ``stm32l5xx.h``

This is the primary HAL header provided by stm32cube. It includes the entire
HAL and all product specific defines.

``stm32cube/stm32cube.h``
^^^^^^^^^^^^^^^^^^^^^^^^^
This is a convenience define provided by this integration. It simply includes
``{family}.h``.

This is useful because there is a lot of commonality between the HAL's of the
different stm32 families. Although the API's are not guaranteed to be
compatible, many basic API's often are (ex. GPIO, UART, etc.). This common
header allows for stm32 family agnostic modules (ex. ``pw_sys_io_stm32``, which
could work with most, if not all families).

``stm32cube/init.h``
^^^^^^^^^^^^^^^^^^^^
As described in the inject_init_ section, if you decide to use the built in
init functionality, a pre main init function call, ``pw_stm32cube_Init()``, is
injected into ST's startup scripts.

This header contains the ``pw_stm32cube_Init()`` function declaration. It
should be included and implemented by target init code.

GN args
-------
The stm32cube GN build arguments are defined in
``$dir_pw_third_party/stm32cube/stm32cube.gni``.

``dir_pw_third_party_stm32cube_xx``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
These should be set to point to the stm32cube directory for each family that
you need to build for. These are optional to set and are only provided for
convenience if you need to build for multiple families in the same project.

``dir_pw_third_party_stm32cube``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This needs to point to the stm32cube directory for the current build.

For multi target projects, the standard practice to set this for each target:

.. code-block:: text

  dir_pw_third_party_stm32cube = dir_pw_third_party_stm32cube_f4


``pw_third_party_stm32cube_PRODUCT``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The product specified in as much detail as possible.
ex. ``stm32f429zit``, ``stm32l552ze``, ``stm32f207zg``, etc.

``pw_third_party_stm32cube_CONFIG``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The pw_source_set that provides ``stm32{family}xx_hal_conf.h``. The default
uses the in-tree ``stm32{family}xx_hal_conf_template.h``.

``pw_third_party_stm32cube_TIMEBASE``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The pw_source_set containing the timebase. The default uses the in-tree
``stm32{family}xx_hal_timebase_tim_template.c``.

``pw_third_party_stm32cube_CMSIS_INIT``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The pw_source_set containing the cmsis init logic. The default uses the in-tree
``system_stm32{family}xx.c``.

``pw_third_party_stm32cube_CORE_INIT``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
pw_source_set containing the core initialization logic. This normally includes
a ``startup_stm32{...}.s`` + a dependent ``pw_linker_script``. The default
``core_init_template`` uses the upstream startup and linker script matching
``pw_third_party_stm32cube_PRODUCT``. If set to "", you must provide your own
linker/startup logic somewhere else in the build.

stm32cube_builder
=================
``stm32cube_builder`` is utility that contains the backend scripts used by
``pw_package/stm32cube`` and the GN build scripts in ``third_party/stm32cube``
to interact with the stm32cube repos. You should only need to interact with
``stm32cube_builder`` directly if you are doing something custom, like
using git submodules instead of pw_package, forking the stm32cube libraries,
interfacing with a different build system, or using your own init.

gen_file_list
-------------
Build systems like GN are unable to depend on arbitrary directories. Instead,
they must have dependencies on specific files. The HAL for each stm32 product
family has different filenames, so ``files.txt`` was created as a workaround.
``files.txt`` is a basic list of all the files in the stm32cube directory with
relavent file extensions. The build system only directly depends on this list,
which must be updated everytime the underlying repos are updated.

This command will generate ``files.txt`` for correctly structured stm32cube
directories.

.. code-block:: bash

  stm32cube_builder gen_file_list /path/to/stm32cube_dir

find_files
----------
Within each stm32 family, there are specific products. Although most of the
HAL is common between products, the init code is almost always different.
``find_files`` looks for all of the files relevant to a particular product
within a stm32cube directory.

The product string should be specified in as much detail as possible because
there are sometimes different defines or init code for submembers of products.

Ex. ``stm32f412cx``, ``stm32f412rx``, ``stm32f412vx``, and ``stm32f412zx`` all
have different init logic, while all ``stm32f439xx`` have the same init.

``find_files`` only ever looks for init (linker + startup scripts) if the
``--init`` flag is provided.

The output is currently only provided in the GN 'scope' format to stdout.
The following variables are output: ``family``, ``product_define``,
``sources``, ``headers``, ``include_dirs``, and the following three if
``--init`` is specified: ``startup``, ``gcc_linker``, ``iar_linker``.

.. code-block:: bash

  stm32cube_builder find_files /path/to/stm32cube_dir stm32{family}{product} [--init]

inject_init
-----------
ST provides init assembly files for every product in ``cmsis_device``. This is
helpful for getting up and running quickly, but they directly call into
``main()`` before initializing the hardware / peripherals. This is because they
expect to do that initialization in ``main()``, then call into the user
application. Upstream Pigweed unit tests expect at least ``sys_io`` to be
initialized before ``main()`` is called.

This command injects a call to ``pw_stm32cube_Init()`` immediately before the
call to ``main()``. This function should be implemented by the target to do
whatever init is necessary (hal init, sys_io init, clock configuration, etc.)

``inject_init`` takes in an ST assembly script and outputs the same script with
the pre main init call. The output is printed to stdout, or to the specified
``--out-startup-path``.

.. code-block:: bash

  stm32cube_builder inject_init /path/to/startup.s [--out-startup-path /path/to/new_startup.s]

icf_to_ld
---------
Pigweed primarily uses GCC for its Cortex-M builds. However, ST only provides
IAR linker scripts in ``cmsis_device`` for most product families. This script
converts from ST's IAR linker script format (.icf) to a basic GCC linker
script (.ld). This is a very basic converter that only works with exactly how
ST currently formats their .icf files.

The output .ld files only contain ``RAM`` and ``FLASH`` sections. Anything more
complicated will require hand customized .ld scripts. Output is printed to
stdout or the specified ``--ld-path``.

.. code-block:: bash

  stm32cube_builder inject_init /path/to/iar_linker.icf [--ld-path /path/to/gcc_linker.ld]

.. _`MCU Components`: https://github.com/STMicroelectronics/STM32Cube_MCU_Overall_Offer#stm32cube-mcu-components
.. _`ST's GitHub page`: https://github.com/STMicroelectronics