| .. _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 |