Varun Sharma | 708d38c | 2021-04-29 09:03:12 -0700 | [diff] [blame] | 1 | .. _module-pw_stm32cube_build: |
| 2 | |
| 3 | ------------------ |
| 4 | pw_stm32cube_build |
| 5 | ------------------ |
| 6 | |
| 7 | The ``pw_stm32cube_build`` module provides helper utilities for building a |
| 8 | target with the stm32cube HAL and/or the stm32cube initialization code. |
| 9 | |
| 10 | The actual GN build files and headers live in ``third_party/stm32cube`` but |
| 11 | are documented here. The rationale for keeping the build files in `third_party` |
| 12 | is that code depending on stm32cube can clearly see that their dependency is on |
| 13 | third party, not pigweed code. |
| 14 | |
| 15 | STM32Cube directory setup |
| 16 | ========================= |
| 17 | Each stm32 product family (ex. F4, L5, etc.) has its own stm32cube libraries. |
| 18 | This integration depends on ST's 3 core `MCU Components`_ instead of their |
| 19 | monolithic `MCU Package`. The components are the hal_driver, cmsis_core, and |
| 20 | cmsis_device. All of these repos exist on `ST's GitHub page`_. Compatible |
| 21 | version tags are specified on the ``README.md`` of each MCU component. |
| 22 | Within a single directory, the following directory/file names are required. |
| 23 | |
| 24 | =============== ============================================= |
| 25 | Dir/File Name Description |
| 26 | =============== ============================================= |
| 27 | hal_driver/ checkout of ``stm32{family}xx_hal_driver`` |
| 28 | cmsis_device/ checkout of ``cmsis_device_{family}`` |
| 29 | cmsis_core/ checkout of ``cmsis_core`` |
| 30 | files.txt list of files generated by `gen_file_list`_ |
| 31 | =============== ============================================= |
| 32 | |
| 33 | pw_package |
| 34 | ---------- |
| 35 | The stm32cube directory can alternatively be setup using ``pw_package``. This |
| 36 | will automatically download compatible repos into the expected folders and |
| 37 | generate the ``files.txt``. |
| 38 | |
| 39 | .. code-block:: bash |
| 40 | |
| 41 | pw package install stm32cube_{family} |
| 42 | |
| 43 | GN build |
| 44 | ======== |
| 45 | The primary ``pw_source_set`` for this integration is |
| 46 | ``$dir_pw_third_party/stm32cube:stm32cube``. This source set includes all of |
| 47 | the HAL, init code, and templates, depending on value of the `GN args`_. |
| 48 | |
| 49 | Headers |
| 50 | ------- |
| 51 | ``$dir_pw_third_party/stm32cube:stm32cube`` contains the following primary |
| 52 | headers that external targets / applications would care about. |
| 53 | |
| 54 | ``{family}.h`` |
| 55 | ^^^^^^^^^^^^^^ |
| 56 | ex. ``stm32f4xx.h``, ``stm32l5xx.h`` |
| 57 | |
| 58 | This is the primary HAL header provided by stm32cube. It includes the entire |
| 59 | HAL and all product specific defines. |
| 60 | |
| 61 | ``stm32cube/stm32cube.h`` |
| 62 | ^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 63 | This is a convenience define provided by this integration. It simply includes |
| 64 | ``{family}.h``. |
| 65 | |
| 66 | This is useful because there is a lot of commonality between the HAL's of the |
| 67 | different stm32 families. Although the API's are not guaranteed to be |
| 68 | compatible, many basic API's often are (ex. GPIO, UART, etc.). This common |
| 69 | header allows for stm32 family agnostic modules (ex. ``pw_sys_io_stm32``, which |
| 70 | could work with most, if not all families). |
| 71 | |
| 72 | ``stm32cube/init.h`` |
| 73 | ^^^^^^^^^^^^^^^^^^^^ |
| 74 | As described in the inject_init_ section, if you decide to use the built in |
| 75 | init functionality, a pre main init function call, ``pw_stm32cube_Init()``, is |
| 76 | injected into ST's startup scripts. |
| 77 | |
| 78 | This header contains the ``pw_stm32cube_Init()`` function declaration. It |
| 79 | should be included and implemented by target init code. |
| 80 | |
| 81 | GN args |
| 82 | ------- |
| 83 | The stm32cube GN build arguments are defined in |
| 84 | ``$dir_pw_third_party/stm32cube/stm32cube.gni``. |
| 85 | |
| 86 | ``dir_pw_third_party_stm32cube_xx`` |
| 87 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 88 | These should be set to point to the stm32cube directory for each family that |
| 89 | you need to build for. These are optional to set and are only provided for |
| 90 | convenience if you need to build for multiple families in the same project. |
| 91 | |
| 92 | ``dir_pw_third_party_stm32cube`` |
| 93 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 94 | This needs to point to the stm32cube directory for the current build. |
| 95 | |
| 96 | For multi target projects, the standard practice to set this for each target: |
| 97 | |
| 98 | .. code-block:: text |
| 99 | |
| 100 | dir_pw_third_party_stm32cube = dir_pw_third_party_stm32cube_f4 |
| 101 | |
| 102 | |
| 103 | ``pw_third_party_stm32cube_PRODUCT`` |
| 104 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 105 | The product specified in as much detail as possible. |
| 106 | ex. ``stm32f429zit``, ``stm32l552ze``, ``stm32f207zg``, etc. |
| 107 | |
| 108 | ``pw_third_party_stm32cube_CONFIG`` |
| 109 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 110 | The pw_source_set that provides ``stm32{family}xx_hal_conf.h``. The default |
| 111 | uses the in-tree ``stm32{family}xx_hal_conf_template.h``. |
| 112 | |
| 113 | ``pw_third_party_stm32cube_TIMEBASE`` |
| 114 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 115 | The pw_source_set containing the timebase. The default uses the in-tree |
| 116 | ``stm32{family}xx_hal_timebase_tim_template.c``. |
| 117 | |
| 118 | ``pw_third_party_stm32cube_CMSIS_INIT`` |
| 119 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 120 | The pw_source_set containing the cmsis init logic. The default uses the in-tree |
| 121 | ``system_stm32{family}xx.c``. |
| 122 | |
| 123 | ``pw_third_party_stm32cube_CORE_INIT`` |
| 124 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 125 | pw_source_set containing the core initialization logic. This normally includes |
| 126 | a ``startup_stm32{...}.s`` + a dependent ``pw_linker_script``. The default |
| 127 | ``core_init_template`` uses the upstream startup and linker script matching |
| 128 | ``pw_third_party_stm32cube_PRODUCT``. If set to "", you must provide your own |
| 129 | linker/startup logic somewhere else in the build. |
| 130 | |
| 131 | stm32cube_builder |
| 132 | ================= |
| 133 | ``stm32cube_builder`` is utility that contains the backend scripts used by |
| 134 | ``pw_package/stm32cube`` and the GN build scripts in ``third_party/stm32cube`` |
| 135 | to interact with the stm32cube repos. You should only need to interact with |
| 136 | ``stm32cube_builder`` directly if you are doing something custom, like |
| 137 | using git submodules instead of pw_package, forking the stm32cube libraries, |
| 138 | interfacing with a different build system, or using your own init. |
| 139 | |
| 140 | gen_file_list |
| 141 | ------------- |
| 142 | Build systems like GN are unable to depend on arbitrary directories. Instead, |
| 143 | they must have dependencies on specific files. The HAL for each stm32 product |
| 144 | family has different filenames, so ``files.txt`` was created as a workaround. |
| 145 | ``files.txt`` is a basic list of all the files in the stm32cube directory with |
| 146 | relavent file extensions. The build system only directly depends on this list, |
| 147 | which must be updated everytime the underlying repos are updated. |
| 148 | |
| 149 | This command will generate ``files.txt`` for correctly structured stm32cube |
| 150 | directories. |
| 151 | |
| 152 | .. code-block:: bash |
| 153 | |
| 154 | stm32cube_builder gen_file_list /path/to/stm32cube_dir |
| 155 | |
| 156 | find_files |
| 157 | ---------- |
| 158 | Within each stm32 family, there are specific products. Although most of the |
| 159 | HAL is common between products, the init code is almost always different. |
| 160 | ``find_files`` looks for all of the files relevant to a particular product |
| 161 | within a stm32cube directory. |
| 162 | |
| 163 | The product string should be specified in as much detail as possible because |
| 164 | there are sometimes different defines or init code for submembers of products. |
| 165 | |
| 166 | Ex. ``stm32f412cx``, ``stm32f412rx``, ``stm32f412vx``, and ``stm32f412zx`` all |
| 167 | have different init logic, while all ``stm32f439xx`` have the same init. |
| 168 | |
| 169 | ``find_files`` only ever looks for init (linker + startup scripts) if the |
| 170 | ``--init`` flag is provided. |
| 171 | |
| 172 | The output is currently only provided in the GN 'scope' format to stdout. |
| 173 | The following variables are output: ``family``, ``product_define``, |
| 174 | ``sources``, ``headers``, ``include_dirs``, and the following three if |
| 175 | ``--init`` is specified: ``startup``, ``gcc_linker``, ``iar_linker``. |
| 176 | |
| 177 | .. code-block:: bash |
| 178 | |
| 179 | stm32cube_builder find_files /path/to/stm32cube_dir stm32{family}{product} [--init] |
| 180 | |
| 181 | inject_init |
| 182 | ----------- |
| 183 | ST provides init assembly files for every product in ``cmsis_device``. This is |
| 184 | helpful for getting up and running quickly, but they directly call into |
| 185 | ``main()`` before initializing the hardware / peripherals. This is because they |
| 186 | expect to do that initialization in ``main()``, then call into the user |
| 187 | application. Upstream Pigweed unit tests expect at least ``sys_io`` to be |
| 188 | initialized before ``main()`` is called. |
| 189 | |
| 190 | This command injects a call to ``pw_stm32cube_Init()`` immediately before the |
| 191 | call to ``main()``. This function should be implemented by the target to do |
| 192 | whatever init is necessary (hal init, sys_io init, clock configuration, etc.) |
| 193 | |
| 194 | ``inject_init`` takes in an ST assembly script and outputs the same script with |
| 195 | the pre main init call. The output is printed to stdout, or to the specified |
| 196 | ``--out-startup-path``. |
| 197 | |
| 198 | .. code-block:: bash |
| 199 | |
| 200 | stm32cube_builder inject_init /path/to/startup.s [--out-startup-path /path/to/new_startup.s] |
| 201 | |
| 202 | icf_to_ld |
| 203 | --------- |
| 204 | Pigweed primarily uses GCC for its Cortex-M builds. However, ST only provides |
| 205 | IAR linker scripts in ``cmsis_device`` for most product families. This script |
| 206 | converts from ST's IAR linker script format (.icf) to a basic GCC linker |
| 207 | script (.ld). This is a very basic converter that only works with exactly how |
| 208 | ST currently formats their .icf files. |
| 209 | |
| 210 | The output .ld files only contain ``RAM`` and ``FLASH`` sections. Anything more |
| 211 | complicated will require hand customized .ld scripts. Output is printed to |
| 212 | stdout or the specified ``--ld-path``. |
| 213 | |
| 214 | .. code-block:: bash |
| 215 | |
| 216 | stm32cube_builder inject_init /path/to/iar_linker.icf [--ld-path /path/to/gcc_linker.ld] |
| 217 | |
| 218 | .. _`MCU Components`: https://github.com/STMicroelectronics/STM32Cube_MCU_Overall_Offer#stm32cube-mcu-components |
| 219 | .. _`ST's GitHub page`: https://github.com/STMicroelectronics |