1.. _bus_emul:
2
3External Bus and Bus Connected Peripherals Emulators
4####################################################
5
6Overview
7========
8
9Zephyr supports a simple emulator framework to support testing of external peripheral drivers
10without requiring real hardware.
11
12Emulators are used to emulate external hardware devices, to support testing of
13various subsystems. For example, it is possible to write an emulator
14for an I2C compass such that it appears on the I2C bus and can be used
15just like a real hardware device.
16
17Emulators often implement special features for testing. For example a
18compass may support returning bogus data if the I2C bus speed is too
19high, or may return invalid measurements if calibration has not yet
20been completed. This allows for testing that high-level code can
21handle these situations correctly. Test coverage can therefore
22approach 100% if all failure conditions are emulated.
23
24Concept
25=======
26
27The diagram below shows application code / high-level tests at the top.
28This is the ultimate application we want to run.
29
30.. figure:: img/arch.svg
31   :align: center
32   :alt: Emulator architecture showing tests, emulators and drivers
33
34Below that are peripheral drivers, such as the AT24 EEPROM driver. We can test
35peripheral drivers using an emulation driver connected via a emulated I2C
36controller/emulator which passes I2C traffic from the AT24 driver to the AT24
37simulator.
38
39Separately we can test the STM32 and NXP I2C drivers on real hardware using API
40tests. These require some sort of device attached to the bus, but with this, we
41can validate much of the driver functionality.
42
43Putting the two together, we can test the application and peripheral code
44entirely on native_sim. Since we know that the I2C driver on the real hardware
45works, we should expect the application and peripheral drivers to work on the
46real hardware also.
47
48Using the above framework we can test an entire application (e.g. Embedded
49Controller) on native_sim using emulators for all non-chip drivers.
50
51With this approach we can:
52
53* Write individual tests for each driver (green), covering all failure modes,
54  error conditions, etc.
55
56* Ensure 100% test coverage for drivers (green)
57
58* Write tests for combinations of drivers, such as GPIOs provided by an I2C GPIO
59  expander driver talking over an I2C bus, with the GPIOs controlling a charger.
60  All of this can work in the emulated environment or on real hardware.
61
62* Write a complex application that ties together all of these pieces and runs on
63  native_sim. We can develop on a host, use source-level debugging, etc.
64
65* Transfer the application to any board which provides the required features
66  (e.g. I2C, enough GPIOs), by adding Kconfig and devicetree fragments.
67
68Creating a Device Driver Emulator
69=================================
70
71The emulator subsystem is modeled on the :ref:`device_model_api`.  You create
72an emulator instance using one of the :c:func:`EMUL_DT_DEFINE()` or
73:c:func:`EMUL_DT_INST_DEFINE()` APIs.
74
75Emulators for peripheral devices reuse the same devicetree node as the real
76device driver. This means that your emulator defines ``DT_DRV_COMPAT`` using the
77same ``compat`` value from the real driver.
78
79.. code-block:: C
80
81  /* From drivers/sensor/bm160/bm160.c */
82  #define DT_DRV_COMPAT bosch_bmi160
83
84  /* From drivers/sensor/bmi160/emul_bmi160.c */
85  #define DT_DRV_COMPAT bosch_bmi160
86
87The ``EMUL_DT_DEFINE()`` function accepts two API types:
88
89  #. ``bus_api`` - This points to the API for the upstream bus that the emulator
90     connects to. The ``bus_api`` parameter is required.  The supported
91     emulated bus types include I2C, SPI, eSPI, and MSPI.
92  #. ``_backend_api`` - This points to the device-class specific backend API for
93     the emulator. The ``_backend_api`` parameter is optional.
94
95The diagram below demonstrates the logical organization of the ``bus_api`` and
96``_backend_api`` using the BC1.2 charging detector driver as the model
97device-class.
98
99.. figure:: img/device_class_emulator.svg
100   :align: center
101   :alt: Device class example, demonstrating BC1.2 charging detectors.
102
103The real code is shown in green, while the emulator code is shown in yellow.
104
105The ``bus_api`` connects the BC1.2 emulators to the ``native_sim`` I2C
106controller. The real BC1.2 drivers are unchanged and operate exactly as if there
107was a physical I2C controller present in the system. The ``native_sim`` I2C
108controller uses the ``bus_api`` to initiate register reads and writes to the
109emulator.
110
111The ``_backend_api`` provides a mechanism for tests to manipulate the emulator
112out of band.  Each device class defines it's own API functions.  The backend API
113functions focus on high-level behavior and do not provide hooks for specific
114emulators.
115
116In the case of the BC1.2 charging detector the backend API provides functions
117to simulate connecting and disconnecting a charger to the emulated BC1.2 device.
118Each emulator is responsible for updating the correct vendor specific registers
119and potentially signalling an interrupt.
120
121Example test flow:
122
123  #. Test registers BC1.2 detection callback using the Zephyr BC1.2 driver API.
124  #. Test connects a charger using the BC1.2 emulator backend.
125  #. Test verifies B1.2 detection callback invoked with correct charger type.
126  #. Test disconnects a charger using the BC1.2 emulator backend.
127
128With this architecture, the same test can be used will all supported drivers in
129the same driver class.
130
131Available Emulators
132===================
133
134Zephyr includes the following emulators:
135
136* I2C emulator driver, allowing drivers to be connected to an emulator so that
137  tests can be performed without access to the real hardware
138
139* SPI emulator driver, which does the same for SPI
140
141* eSPI emulator driver, which does the same for eSPI. The emulator is being
142  developed to support more functionalities.
143
144* MSPI emulator driver, allowing drivers to be connected to an emulator so that
145  tests can be performed without access to the real hardware.
146
147I2C Emulation features
148----------------------
149
150In the binding of the I2C emulated bus, there's a custom property for address
151based forwarding. Given the following devicetree node:
152
153.. code-block:: devicetree
154
155   i2c0: i2c@100 {
156     status = "okay";
157     compatible = "zephyr,i2c-emul-controller";
158     clock-frequency = <I2C_BITRATE_STANDARD>;
159     #address-cells = <1>;
160     #size-cells = <0>;
161     #forward-cells = <1>;
162     reg = <0x100 4>;
163     forwards = <&i2c1 0x20>;
164   };
165
166The final property, ``forwards`` indicates that any read/write requests sent to
167address ``0x20`` should be sent to ``i2c1`` with the same address. This allows
168us to test both the controller and the target end of the communication on the
169same image.
170
171.. note::
172   The ``#forward-cells`` attribute should always be 1. Each entry in the
173   ``forwards`` attribute consists of the phandle followed by the address. In
174   the example above, ``<&i2c1 0x20>`` will forward all read/write operations
175   made to ``i2c0`` at port ``0x20`` to ``i2c1`` on the same port. Since no
176   additional cells are used by the emulated controller, the number of cells
177   should remain 1.
178
179Samples
180=======
181
182Here are some examples present in Zephyr:
183
184#. Bosch BMI160 sensor driver connected via both I2C and SPI to an emulator:
185
186   .. zephyr-app-commands::
187      :zephyr-app: tests/drivers/sensor/bmi160
188      :board: native_sim
189      :goals: build
190
191#. The same test can be built with a second EEPROM which is an Atmel AT24 EEPROM driver
192   connected via I2C an emulator:
193
194   .. zephyr-app-commands::
195      :zephyr-app: tests/drivers/eeprom/api
196      :board: native_sim
197      :goals: build
198      :gen-args: -DDTC_OVERLAY_FILE=at2x_emul.overlay -DEXTRA_CONF_FILE=at2x_emul.conf
199
200API Reference
201=============
202
203.. doxygengroup:: io_emulators
204