220 lines
8.9 KiB
ReStructuredText
220 lines
8.9 KiB
ReStructuredText
.. _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
|