Skip to content
192 changes: 192 additions & 0 deletions doc/develop/api/api_conventions.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
.. _api_conventions:

API Conventions
###############

Zephyr provides a few programming interfaces that users can use for creating their applications.
Zephyr's API space includes the following areas:

- C programming interface (function prototypes, structures, and macros), provided in C header files
- Configuration system (Kconfig)
- Hardware description system (Devicetree)

Other areas, such as the build system (CMake), may also be seen as Zephyr's API. However, any area
that is not explicitly listed herein is not considered Zephyr's API as of today.

API classification
******************
The files that define the Zephyr APIs may contain symbols intended for different usage. The intended
API usage is designated by the API class. Zephyr APIs are classified as:

Private
These APIs are intended for use within the boundary of a :term:`software component`. Private APIs
defined in the main Zephyr tree are not subject to :ref:`api_lifecycle`. Therefore, they can be changed or
removed at any time. Changes to the private APIs may not be documented at all, and are not included in the
migration guide.

Internal
In general, these APIs are intended for use only between certain software components that are
located in the main Zephyr tree. The context where the API is called or implemented is well defined. For
example, functions prefixed with `arch_` are intended for use by the Zephyr kernel to invoke
architecture-specific code. An API is classified as internal on a case by case basis.
Internal APIs should not be used by out-of-tree code. Internal APIs are not subject
to :ref:`api_lifecycle`. Therefore, they can be changed or removed at any time. However, changes to the
internal APIs must be documented in the migration guide.

Public
These APIs intended for use from any :term:`software component`. Public APIs may be used in-tree
and out-of-tree. Public APIs are subject to the :ref:`api_lifecycle`. Therefore, changes to an
API are introduced and documented according to the rules defined for the API life cycle. This includes
documenting any breaking changes in the migration guide.

Note, that only APIs defined in the main Zephyr tree are subject to :ref:`api_lifecycle`. External projects
used as :ref:`modules` may define their own rules for API lifecycle.

Zephyr is a constantly evolving project and API classification may change over time. A Private or
Internal API may be promoted to Internal or Public API, respectively. Zephyr users are encouraged to
follow :ref:`rfcs` process to recommend changes in API classification.

The following sections provide guidelines on how to identify the class of an API depending on its
type.

Header files contents
=====================
Private
Functions and data types declared in header files located in
:zephyr_file:`include/zephyr/private/`. In addition, private symbols are prefixed with ``z_``.
Due to historical reasons some APIs prefixed with ``z_`` are public.

Internal
Functions and data types declared in :zephyr_file:`include/zephyr/internal`. In addition, Internal
APIs must use ``@internal`` doxygen command.

Public
Functions and data types declared in header files located in :zephyr_file:`include/zephyr/`.

In addition, the following prefixes are reserved by Zephyr kernel for use in Zephyr Public APIs:

.. list-table:: Prefixes and Descriptions
:header-rows: 1
:widths: 10 40 40
:stub-columns: 1

* - Prefix
- Description
- Example
* - ``atomic_``
- Denotes an atomic operation.
- :c:func:`atomic_inc`
* - ``device_``
- Denotes an API relating to devices and their initialization.
- :c:func:`device_get_binding`
* - ``irq_``
- Denotes an IRQ management operation.
- :c:func:`irq_disable`
* - ``k_``
- Kernel-specific function.
- :c:func:`k_malloc`
* - ``sys_``
- Catch-all for APIs that do not fit into the other namespaces.
- :c:func:`sys_write32`

Kconfig symbols
===============
All Kconfig symbols are Public. The :ref:`api_lifecycle` of a Kconfig symbol is defined by the
:ref:`api_lifecycle` of a :term:`software component` to which the binding belongs. For example,
Kconfig symbols defined for regulators follow the lifecycle of the :ref:`regulator_api`.

Devicetree bindings
===================
Device tree bindings and their content are Public. The :ref:`api_lifecycle` of a binding is defined
by the :ref:`api_lifecycle` of a :term:`software component` to which the binding belongs. For
example, bindings defined for regulators follow the lifecycle of the :ref:`regulator_api`.

Breaking and non-breaking changes
**********************************

This section categorizes common changes as breaking or non-breaking for each API type.

.. note::
This section focuses on API source compatibility. ABI (Application Binary Interface) compatibility
is out of scope, as it is assumed that applications recompile their entire code base when updating
Zephyr versions.

.. list-table:: C API Changes
:header-rows: 1
:widths: 50 50

* - Breaking Changes
- Non-Breaking Changes
* - | **Functions:**
| • Remove or rename function
| • Change return type
| • Add, remove, or reorder parameters
| • Change parameter types
| • Change behavior or error codes
|
| **Data types:**
| • Remove or rename struct/union/enum
| • Modify struct fields (remove, rename, change type)
| • Remove/rename enum values
| • Change enum constant values
|
| **Macros:**
| • Remove or rename macro
| • Change macro value affecting behavior
- | **Functions:**
| • Add new function
| • Deprecate (not remove) function
| • Improve documentation
|
| **Data types:**
| • Add new struct/union/enum
| • Add enum value at end
| • Add struct field at end (with versioning)
|
| **Macros:**
| • Add new macro

.. list-table:: Kconfig Changes
:header-rows: 1
:widths: 50 50

* - Breaking Changes
- Non-Breaking Changes
* - | • Remove or rename symbol
| • Change symbol type (e.g., bool to int)
| • Remove default without migration path
| • Change dependencies breaking configs
| • Change symbol semantics
- | • Add new symbol
| • Change help text or prompt
| • Change default (backward compatible)
| • Add ranges/choices including valid values
| • Deprecate with migration path

.. list-table:: Devicetree Changes
:header-rows: 1
:widths: 50 50

* - Breaking Changes
- Non-Breaking Changes
* - | • Remove binding file
| • Remove or rename required property
| • Change property type
| • Make optional property required (no default)
| • Change phandle-array cell meaning
| • Remove compatible string
- | • Add binding file
| • Add optional property
| • Add compatible string
| • Add property default
| • Make required property optional
| • Deprecate property (keep support)

API Lifecycle Impact
====================

Breaking changes require different handling based on API classification:

- **Private APIs**: Changes allowed anytime without documentation
- **Internal APIs**: Changes allowed but must document in migration guide
- **Public APIs**: Must follow :ref:`api_lifecycle` (Experimental → Unstable → Stable)
17 changes: 14 additions & 3 deletions doc/develop/api/design_guidelines.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ specifying the signature of a callback:
An exception to providing ``user_data`` as the last parameter may be
allowed when the callback itself was provided through a structure that
will be embedded in another structure. An example of such a case is
:c:struct:`gpio_callback`, normally defined within a data structure
:c:type:`gpio_callback`, normally defined within a data structure
specific to the code that also defines the callback function. In those
cases further context can accessed by the callback indirectly by
:c:macro:`CONTAINER_OF`.
Expand All @@ -45,7 +45,7 @@ Examples
void handle_timeout(struct k_timer *timer)
{ ... }

The assumption here, as with :c:struct:`gpio_callback`, is that the
The assumption here, as with :c:type:`gpio_callback`, is that the
timer is embedded in a structure reachable from
:c:macro:`CONTAINER_OF` that can provide additional context to the
callback.
Expand All @@ -62,7 +62,7 @@ Examples
This provides more complete useful information, including which
counter channel timed-out and the counter value at which the timeout
occurred, as well as user context which may or may not be the
:c:struct:`counter_alarm_cfg` used to register the callback, depending
:c:type:`counter_alarm_cfg` used to register the callback, depending
on user needs.

Conditional Data and APIs
Expand Down Expand Up @@ -103,9 +103,20 @@ The Kconfig flag used to enable the feature should be added to the
``PREDEFINED`` variable in :file:`doc/zephyr.doxyfile.in` to ensure the
conditional API and functions appear in generated documentation.

Subsystem namespaces
********************

A subsystem can define its own naming conventions for symbols as long as the scheme doesn't collide
with Zephyr naming conventions :ref:`api_conventions`. The naming convention should include a
namespace prefix (for example, bt\_ for Bluetooth LE, or net\_ for IP). This limits possible
collisions with symbols defined by an application.

Return Codes
************

Zephyr uses the standard codes in ``errno.h`` for all APIs. As a general rule, 0 indicates success;
a negative ``errno.h`` code indicates an error condition.

Implementations of an API, for example an API for accessing a peripheral might
implement only a subset of the functions that is required for minimal operation.
A distinction is needed between APIs that are not supported and those that are
Expand Down
1 change: 1 addition & 0 deletions doc/develop/api/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ API Status and Guidelines
:maxdepth: 1

overview.rst
api_conventions.rst
api_lifecycle.rst
design_guidelines.rst
terminology.rst
5 changes: 2 additions & 3 deletions doc/glossary.rst
Original file line number Diff line number Diff line change
Expand Up @@ -169,9 +169,8 @@ Glossary of Terms
features, and that the vendor typically names and markets together.

software component
A software component is a self-contained, modular, and replaceable part of
the Zephyr source code. A driver, a subsystem or an applications are all
examples of software components present in Zephyr.
A software component is a self-contained, modular, and replaceable part of the Zephyr source
code. A driver or subsystem is an example of a software component present in Zephyr.

subsystem
A subsystem refers to a logically distinct part of the operating system
Expand Down