491 lines
16 KiB
ReStructuredText
491 lines
16 KiB
ReStructuredText
.. _board_porting_guide:
|
|
|
|
Board Porting Guide
|
|
###################
|
|
|
|
When building an application you must specify the target hardware and
|
|
the exact board or model. Specifying the board name results in a binary that
|
|
is suited for the target hardware by selecting the right Zephyr features and
|
|
components and setting the right Zephyr configuration for that specific target
|
|
hardware.
|
|
|
|
A board is defined as a special configuration of an SoC with possible additional
|
|
components.
|
|
For example, a board might have sensors and flash memory implemented as
|
|
additional features on top of what the SoC provides. Such additional hardware is
|
|
configured and referenced in the Zephyr board configuration.
|
|
|
|
The board implements at least one SoC and thus inherits all of the features
|
|
that are provided by the SoC. When porting a board to Zephyr, you should
|
|
first make sure the SoC is implemented in Zephyr.
|
|
|
|
Hardware Configuration Hierarchy
|
|
********************************
|
|
|
|
Hardware definitions in Zephyr follow a well-defined hierarchy of configurations
|
|
and layers, below are the layers from top to bottom:
|
|
|
|
- Board
|
|
- SoC
|
|
- SoC Series
|
|
- SoC Family
|
|
- CPU Core
|
|
- Architecture
|
|
|
|
This design contributes to code reuse and implementation of device drivers and
|
|
features at the bottom of the hierarchy making a board configuration as simple
|
|
as a selection of features that are implemented by the underlying layers. The
|
|
figures below shows this hierarchy with a few example of boards currently
|
|
available in the source tree:
|
|
|
|
.. figure:: board/hierarchy.png
|
|
:width: 500px
|
|
:align: center
|
|
:alt: Configuration Hierarchy
|
|
|
|
Configuration Hierarchy
|
|
|
|
|
|
Hierarchy Example
|
|
|
|
+------------+-----------+--------------+------------+--------------+---------+
|
|
|Board |FRDM K64F |nRF52 NITROGEN|nRF51XX |Quark SE C1000|Arduino |
|
|
| | | | |Devboard |101 |
|
|
+============+===========+==============+============+==============+=========+
|
|
|SOC |MK64F12 |nRF52832 |nRF51XX |Quark SE C1000|Curie |
|
|
+------------+-----------+--------------+------------+--------------+---------+
|
|
|SOC Series |Kinetis K6x|Nordic NRF52 |Nordic NRF51|Quark SE |Quark SE |
|
|
| |Series | | | | |
|
|
+------------+-----------+--------------+------------+--------------+---------+
|
|
|SOC Family |NXP Kinetis|Nordic NRF5 |Nordic NRF5 |Quark |Quark |
|
|
+------------+-----------+--------------+------------+--------------+---------+
|
|
|CPU Core |Cortex-M4 |Cortex-M4 |Cortex-M0 |Lakemont |Lakemont |
|
|
+------------+-----------+--------------+------------+--------------+---------+
|
|
|Architecture|ARM |ARM |ARM |x86 |x86 |
|
|
+------------+-----------+--------------+------------+--------------+---------+
|
|
|
|
|
|
Architecture
|
|
============
|
|
If your CPU architecture is already supported by Zephyr, there is no
|
|
architecture work involved in porting to your board. If your CPU architecture
|
|
is not supported by the Zephyr kernel, you can add support by following the
|
|
instructions available at :ref:`architecture_porting_guide`.
|
|
|
|
CPU Core
|
|
========
|
|
|
|
Some OS code depends on the CPU core that your board is using. For
|
|
example, a given CPU core has a specific assembly language instruction set, and
|
|
may require special cross compiler or compiler settings to use the appropriate
|
|
instruction set.
|
|
|
|
If your CPU architecture is already supported by Zephyr, there is no CPU core
|
|
work involved in porting to your platform or board. You need only to select the
|
|
appropriate CPU in your configuration and the rest will be taken care of by the
|
|
configuration system in Zephyr which will select the features implemented
|
|
by the corresponding CPU.
|
|
|
|
Platform
|
|
========
|
|
|
|
This layer implements most of the features that need porting and is split into
|
|
three layers to allow for code reuse when dealing with implementations with
|
|
slight differences.
|
|
|
|
SoC Family
|
|
----------
|
|
|
|
This layer is a container of all SoCs of the same class that, for example
|
|
implement one single type of CPU core but differ in peripherals and features.
|
|
The base hardware will in most cases be the same across all SoCs and MCUs of
|
|
this family.
|
|
|
|
SoC Series
|
|
----------
|
|
|
|
Moving closer to the SoC, the series is derived from an SoC family. A series is
|
|
defined by a feature set that serves the purpose of distinguishing different
|
|
SoCs belonging to the same family.
|
|
|
|
SoC
|
|
---
|
|
|
|
Finally, an SoC is actual hardware component that is physically available on a
|
|
board.
|
|
|
|
Board
|
|
=====
|
|
|
|
A board implements an SoC with all its features, together with peripherals
|
|
available on the board that differentiates the board with additional interfaces
|
|
and features not available in the SoC.
|
|
|
|
.. _default_board_configuration:
|
|
|
|
Default board configuration
|
|
***************************
|
|
|
|
When porting Zephyr to a board, you must provide the board's default
|
|
Kconfig configuration, which is used in application builds unless explicitly
|
|
overridden.
|
|
|
|
.. note::
|
|
|
|
See the :ref:`kconfig_tips_and_tricks` page for some best practices and tips
|
|
when writing Kconfig files.
|
|
|
|
In order to provide consistency across the various boards and ease the work of
|
|
users providing applications that are not board specific, the following
|
|
guidelines should be followed when porting a board:
|
|
|
|
- Provide pin and driver configuration that matches the board's valuable
|
|
components such as sensors, buttons or LEDs, and communication interfaces
|
|
such as USB, Ethernet connector, or Bluetooth/Wi-Fi chip.
|
|
|
|
- When a well-known connector is present (such as used on an Arduino or
|
|
96board), configure pins to fit this connector.
|
|
|
|
- Configure components that enable the use of these pins, such as
|
|
configuring an SPI instance for Arduino SPI.
|
|
|
|
- Configure an output for the console.
|
|
|
|
- Propose and configure a default network interface.
|
|
|
|
- Enable all GPIO ports.
|
|
|
|
.. _setting_configuration_values:
|
|
|
|
Setting configuration values
|
|
============================
|
|
|
|
Kconfig symbols can be set to their ``BOARD``-specific values in one of two
|
|
ways. The right method to use depends on whether the symbol is *visible* or
|
|
not.
|
|
|
|
|
|
Visible and invisible Kconfig symbols
|
|
-------------------------------------
|
|
|
|
Kconfig symbols come in two varieties:
|
|
|
|
- A Kconfig symbol defined with a prompt is *visible*, and can be configured from
|
|
the ``menuconfig`` configuration interface.
|
|
|
|
- A Kconfig symbol defined without a prompt is *invisible*. The user has no
|
|
direct control over its value.
|
|
|
|
Here are some examples of visible and invisible symbols:
|
|
|
|
.. code-block:: none
|
|
|
|
config NOT_VISIBLE
|
|
bool
|
|
default FOO
|
|
|
|
config VISIBLE_1
|
|
string
|
|
prompt "Foo value"
|
|
|
|
config VISIBLE_2
|
|
# Shorthand for giving a type and a prompt at the same time. This is
|
|
# the preferred style in Zephyr.
|
|
bool "Enable stuff"
|
|
|
|
|
|
Configuring visible Kconfig symbols
|
|
-----------------------------------
|
|
|
|
Default ``BOARD``-specific configuration values for visible Kconfig symbols
|
|
*should* be given in :file:`boards/ARCHITECTURE/BOARD/BOARD_defconfig`, which
|
|
uses the standard Kconfig :file:`.config` file syntax.
|
|
|
|
|
|
Configuring invisible Kconfig symbols
|
|
-------------------------------------
|
|
|
|
``BOARD``-specific configuration values for invisible Kconfig symbols *must* be
|
|
given in :file:`boards/ARCHITECTURE/BOARD/Kconfig.defconfig`, which uses
|
|
Kconfig syntax.
|
|
|
|
.. note::
|
|
|
|
Assignments in :file:`.config` files have no effect on invisible symbols,
|
|
so this scheme is not just an organizational issue.
|
|
|
|
Assigning values in :file:`Kconfig.defconfig` relies on being able to define a
|
|
Kconfig symbol in multiple locations. As an example, say we want to set
|
|
``FOO_WIDTH`` below to 32:
|
|
|
|
.. code-block:: none
|
|
|
|
config FOO_WIDTH
|
|
int
|
|
|
|
To do this, we extend the definition of ``FOO_WIDTH`` as follows, in
|
|
:file:`Kconfig.defconfig`:
|
|
|
|
.. code-block:: none
|
|
|
|
if BOARD_MY_BOARD
|
|
|
|
config FOO_WIDTH
|
|
default 32
|
|
|
|
endif
|
|
|
|
.. note::
|
|
|
|
Since the type of the symbol (``int``) has already been given at the first
|
|
definition location, it does not need to be repeated here.
|
|
|
|
``default`` values in :file:`Kconfig.defconfig` files have priority over
|
|
``default`` values given on the "base" definition of a symbol. Internally, this
|
|
is implemented by including the :file:`Kconfig.defconfig` files first. Kconfig
|
|
uses the first ``default`` with a satisfied condition, where an empty condition
|
|
works like ``if y`` (is always satisfied).
|
|
|
|
.. note::
|
|
|
|
``range`` properties on ``int`` and ``hex`` symbols work the same way, and
|
|
can also be added or overridden in :file:`Kconfig.defconfig` files.
|
|
|
|
If you want a symbol to only be user-configurable on some boards, make its base
|
|
definition have no prompt, and then add a prompt to it in the
|
|
:file:`Kconfig.defconfig` files of the boards where it should be configurable.
|
|
|
|
.. note::
|
|
|
|
Prompts added in :file:`Kconfig.defconfig` files show up at the location of
|
|
the :file:`Kconfig.defconfig` file in the ``menuconfig`` interface, rather
|
|
than at the location of the base definition of the symbol.
|
|
|
|
|
|
Configuring choices
|
|
-------------------
|
|
|
|
There are two ways to configure a Kconfig ``choice``:
|
|
|
|
1. By setting one of the choice symbols to ``y`` in :file:`BOARD_defconfig`.
|
|
|
|
.. note::
|
|
|
|
Setting one choice symbol to ``y`` automatically gives all other choice
|
|
symbols the value ``n``.
|
|
|
|
If multiple choice symbols are set to ``y``, only the last one set to
|
|
``y`` will be honored (and the rest will get the value ``n``). This
|
|
allows a choice selection from a board :file:`defconfig` file to be
|
|
overridden from an application :file:`prj.conf` file.
|
|
|
|
2. By changing the ``default`` of the choice in :file:`Kconfig.defconfig`.
|
|
|
|
As with symbols, changing the default for a choice is done by defining the
|
|
choice in multiple locations. For this to work, the choice must have a name.
|
|
|
|
As an example, assume that a choice has the following base definition (here,
|
|
the name of the choice is ``FOO``):
|
|
|
|
.. code-block:: none
|
|
|
|
choice FOO
|
|
bool "Foo choice"
|
|
default B
|
|
|
|
config A
|
|
bool "A"
|
|
|
|
config B
|
|
bool "B"
|
|
|
|
endchoice
|
|
|
|
To change the default symbol of ``FOO`` to ``A``, you would add the
|
|
following definition to :file:`Kconfig.defconfig`:
|
|
|
|
.. code-block:: none
|
|
|
|
choice FOO
|
|
default A
|
|
endchoice
|
|
|
|
The :file:`Kconfig.defconfig` method should be used when the dependencies of
|
|
the choice might not be satisfied. In that case, you're setting the default
|
|
selection whenever the user makes the choice visible.
|
|
|
|
|
|
Motivation
|
|
----------
|
|
|
|
One motivation for this configuration scheme is to avoid making fixed
|
|
``BOARD``-specific settings configurable in the ``menuconfig`` interface. If
|
|
all configuration were done via :file:`BOARD_defconfig`, all symbols would have
|
|
to be visible, as values given in :file:`BOARD_defconfig` have no effect on
|
|
invisible symbols.
|
|
|
|
Having fixed settings be user-configurable might be confusing, and would allow
|
|
the user to create broken configurations.
|
|
|
|
.. _kconfig_extensions:
|
|
|
|
Kconfig extensions
|
|
==================
|
|
|
|
Zephyr uses the `Kconfiglib <https://github.com/ulfalizer/Kconfiglib>`_
|
|
implementation of `Kconfig
|
|
<https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt>`_, which
|
|
includes some Kconfig extensions.
|
|
|
|
Environment variables in ``source`` statements are expanded directly in
|
|
Kconfiglib, meaning no ``option env="ENV_VAR"`` "bounce" symbols need to be
|
|
defined. If you need compatibility with the C Kconfig tools for an out-of-tree
|
|
Kconfig tree, you can still add such symbols, but they must have the same name
|
|
as the corresponding environment variables.
|
|
|
|
.. note::
|
|
|
|
``option env`` has been removed from the C tools in Linux 4.18 as well.
|
|
|
|
The recommended syntax for referencing environment variables is now
|
|
``$(FOO)`` rather than ``$FOO``. This uses the new `Kconfig preprocessor
|
|
<https://raw.githubusercontent.com/torvalds/linux/master/Documentation/kbuild/kconfig-macro-language.txt>`_.
|
|
|
|
The following Kconfig extensions are available:
|
|
|
|
- The ``source`` statement supports glob patterns and includes each matching
|
|
file. A pattern is required to match at least one file.
|
|
|
|
Consider the following example:
|
|
|
|
.. code-block:: none
|
|
|
|
source "foo/bar/*/Kconfig"
|
|
|
|
If the pattern ``foo/bar/*/Kconfig`` matches the files
|
|
:file:`foo/bar/baz/Kconfig` and :file:`foo/bar/qaz/Kconfig`, the statement
|
|
above is equivalent to the following two ``source`` statements:
|
|
|
|
.. code-block:: none
|
|
|
|
source "foo/bar/baz/Kconfig"
|
|
source "foo/bar/qaz/Kconfig"
|
|
|
|
.. note::
|
|
|
|
The wildcard patterns accepted are the same as for the Python `glob
|
|
<https://docs.python.org/3/library/glob.html>`_ module.
|
|
|
|
If no files match the pattern, an error is generated.
|
|
|
|
For cases where it's okay for a pattern to match no files (or for a plain
|
|
filename to not exist), a separate ``osource`` (*optional source*) statement
|
|
is available. ``osource`` is a no-op in case of no matches.
|
|
|
|
.. note::
|
|
|
|
``source`` and ``osource`` are analogous to ``include`` and
|
|
``-include`` in Make.
|
|
|
|
- An ``rsource`` statement is available for including files specified with a
|
|
relative path. The path is relative to the directory of the :file:`Kconfig`
|
|
file that contains the ``rsource`` statement.
|
|
|
|
As an example, assume that :file:`foo/Kconfig` is the top-level
|
|
:file:`Kconfig` file, and that :file:`foo/bar/Kconfig` has the following
|
|
statements:
|
|
|
|
.. code-block:: none
|
|
|
|
source "qaz/Kconfig1"
|
|
rsource "qaz/Kconfig2"
|
|
|
|
This will include the two files :file:`foo/qaz/Kconfig1` and
|
|
:file:`foo/bar/qaz/Kconfig2`.
|
|
|
|
``rsource`` can be used to create :file:`Kconfig` "subtrees" that can be
|
|
moved around freely.
|
|
|
|
.. note::
|
|
|
|
``rsource`` also supports glob patterns.
|
|
|
|
- An ``orsource`` statement, which combines ``osource`` and ``rsource``.
|
|
|
|
For example, the following statement will include :file:`Kconfig1` and
|
|
:file:`Kconfig2` from the current directory (if they exist):
|
|
|
|
.. code-block:: none
|
|
|
|
orsource "Kconfig[12]"
|
|
|
|
- ``def_int``, ``def_hex``, and ``def_string`` keywords, which are analogous to
|
|
``def_bool``. These set the type and add a ``default`` at the same time.
|
|
|
|
|
|
Old Zephyr Kconfig behavior for defaults
|
|
========================================
|
|
|
|
Prior to early August 2018 (during development of Zephyr 1.13), Zephyr used a
|
|
custom patch that made Kconfig prefer the last ``default`` with a satisfied
|
|
condition, instead of the first one. This patch has been removed.
|
|
|
|
Consider this example:
|
|
|
|
.. code-block:: none
|
|
|
|
config FOO
|
|
string
|
|
default "first" if n
|
|
default "second"
|
|
default "third" if n
|
|
default "fourth"
|
|
default "fifth" if n
|
|
|
|
With the old custom behavior, ``FOO`` got the value ``"fourth"``, from the last
|
|
``default`` with a satisfied condition.
|
|
|
|
With the new behavior, ``FOO`` gets the value ``"second"``, from the first
|
|
``default`` with a satisfied condition. This is standard Kconfig behavior.
|
|
|
|
There are two issues with the old behavior:
|
|
|
|
1. It's inconsistent with how Kconfig works in other projects, which is
|
|
confusing.
|
|
|
|
2. Due to oversights, earlier ``range`` properties were still preferred, as
|
|
well as earlier ``default`` properties on choices.
|
|
|
|
In addition to being inconsistent, this made it impossible to override
|
|
``range`` properties and ``default`` properties on choices if the base
|
|
definition of the symbol/choice already had ``range``/``default``
|
|
properties.
|
|
|
|
.. note::
|
|
|
|
If you're maintaining an external project that has symbols with multiple
|
|
``default`` properties, you will need to swap the order of the ``default``
|
|
properties to get the same behavior as before.
|
|
|
|
If your external project is modifying symbols in the base Zephyr
|
|
configuration by sourcing ``Kconfig.zephyr`` and adding additional symbol
|
|
definitions, you might need to move the ``source`` from before the extra
|
|
symbol definitions to after them.
|
|
|
|
|
|
More Kconfig resources
|
|
======================
|
|
|
|
The official documentation for Kconfig is `kconfig-language.txt
|
|
<https://raw.githubusercontent.com/torvalds/linux/master/Documentation/kbuild/kconfig-language.txt>`_
|
|
and `kconfig-macro-language.txt
|
|
<https://raw.githubusercontent.com/torvalds/linux/master/Documentation/kbuild/kconfig-macro-language.txt>`_.
|
|
|
|
The :ref:`kconfig_tips_and_tricks` page has some best practices and
|
|
tips for writing Kconfig files.
|
|
|
|
The `kconfiglib.py
|
|
<https://raw.githubusercontent.com/zephyrproject-rtos/zephyr/master/scripts/kconfig/kconfiglib.py>`_
|
|
docstring (at the top of the file) goes over how symbol values are calculated
|
|
in detail.
|