summaryrefslogtreecommitdiff
path: root/docs/zephyr/zephyr_shim.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/zephyr/zephyr_shim.md')
-rw-r--r--docs/zephyr/zephyr_shim.md381
1 files changed, 381 insertions, 0 deletions
diff --git a/docs/zephyr/zephyr_shim.md b/docs/zephyr/zephyr_shim.md
new file mode 100644
index 0000000000..fac0383aff
--- /dev/null
+++ b/docs/zephyr/zephyr_shim.md
@@ -0,0 +1,381 @@
+[TOC]
+
+# Zephyr Shimming How-To
+
+## Objective
+
+Allow a subset of the platform/ec code to be built as part of the Zephyr-based
+EC without needing to land code into upstream zephyr, or our zephyr-chrome
+repository.
+
+## Background
+
+Now that Google has joined [Zephyr OS](https://www.zephyrproject.org/), the EC
+team is moving toward it instead of platform/ec code on embedded controllers for
+future Chrome OS devices. See the
+[originally proposed idea](https://goto.google.com/cros-ec-rtos) and a more
+specific [Zephyr process doc](https://goto.google.com/zephyr-structure) of what
+future development on Zephyr will look like.
+
+Simply put, we want to move to Zephyr OS to use an open-source embedded OS that
+has a vibrant community. The embedded OS scene for the industry is very
+fragmented, with various parties using their own custom solution. We see the
+strong open-source community at Zephyr as potentially helping to consolidate
+efforts in the embedded controller space. It will also benefit our partners
+(both chip vendors and OEMs) since they should only have to support one embedded
+OS (i.e., Zephyr) for both their Chrome OS and Windows based devices.
+
+Migrating to use Zephyr fully is going to take a few years. We do not want to
+diverge from the active development happening on platform/ec code. We
+potentially want to ship a product using Zephyr before the migration is
+complete.
+
+## Design ideas
+
+In order to reuse `platform/ec` development , we shim "active" `platform/ec`
+code as a
+[Zephyr Module](https://docs.zephyrproject.org/latest/guides/modules.html). This
+requires us to add some Zephyr specific code in a `zephyr` directory in the
+`platform/ec` codebase. Once we release a Zephyr-based EC, then we can turn down
+platform/ec for future development and work on migrating the platform/ec-module
+code out of the module directory and into a first-class Zephyr code format -- in
+the local
+[Chrome Zephyr repo](https://chromium.googlesource.com/chromiumos/platform/zephyr-chrome/+/HEAD)
+and ultimately [upstream](https://github.com/zephyrproject-rtos/zephyr).
+
+For platform/ec code that is stable and not under active development, the Zephyr
+team may port that code to Zephyr, thus skipping the shimming process.
+
+### Subsystems of interest
+
+#### With Shim
+
+We shim the following subsystems (non-exhaustive).
+
+* USB-C: TCPC, PPC, MUX, TCPMv2
+* Charge Manager
+* SoC Power Sequencing
+* Sensors, if Intel’s HID-based solution is delayed in getting to Zephyr
+ upstream
+
+#### Little-to-No Shim
+
+We adopt upstream Zephyr or skip the shimming process (non-exhaustive).
+
+* CBI and dependent EEPROM code
+ * The format is stable. We pull in the list of CBI tags from platform/ec
+ though
+* EFS2, Vboot, RO/RW split
+ * Adjusting flash layout would be difficult to shim, and the concept is
+ very stable.
+ * We may shim some core EFS2 logic
+* Host command framework
+* Sensors, if Intel’s HID-based solution getts to Zephyr upstream and passes
+ CTS
+* Keyboard and keycode scanning support
+ * We may shim the newer Vivaldi feature.
+* Console support
+ * We allow individual console commands via DECLARE\_CONSOLE\_COMMAND to be
+ shimmed to Zephyr. These convert commands to work with Zephyr's shell
+ subsystem.
+* I2C
+
+### New content in platform/ec
+
+Add the `src/platform/ec/zephyr` folder with:
+
+* [Module integration files](https://docs.zephyrproject.org/latest/guides/modules.html#build-system-integration),
+ e.g., module.yml, CMakeLists.txt, and KConfig.
+ * **module.yml** is the required entry point (must be located at
+ _zephyr/module.yml_ in the repository) for Zephyr modules, and declares
+ the location of Kconfig and CMakeLists.txt files used by the Zephyr
+ build system.
+ * **CMakeLists.txt** replicates build logic for the files being shimmed,
+ outside of the platform/ec Makefile.
+ * **Kconfig** will declare any CONFIG\_\* options which are important to
+ expose from platform/ec code to the Zephyr build.
+* Shim code to translate platform/ec code into Zephyr code
+ * For example, redefine platform/ec’s
+ [`DECLARE_HOST_COMMAND`](https://source.chromium.org/chromiumos/chromiumos/codesearch/+/HEAD:src/platform/ec/include/host_command.h;l=256;drc=514923bc59f5a3435dbb7cbf348735ed41889ffe)
+ to map to Zephyr's upstream
+ [`EC_HOST_CMD_HANDLER`](https://github.com/zephyrproject-rtos/zephyr/blob/d7468bf836b75c29980441f294a61eae6bf4bc75/include/ec_host_cmd.h#L73)
+ macro. This allows us to compile select platform/ec files in the Zephyr
+ build.
+
+### Namespace Collisions
+
+One significant issue of mixing Zephyr headers with our existing EC code is that
+we currently have many names colliding with the Zephyr code. For example,
+Zephyr's atomic functions also are named `atomic_add`, `atomic_or`, ...,
+however, have a different API from our EC's atomic functions. This is critical,
+since atomic operations are often used in `static inline` functions placed in
+header files.
+
+In some cases, we are able to hack around these collisions by creating macros
+and functions which are compatible with both Zephyr and our EC's usages. For
+example, we can create a modified `IS_ENABLED` which accepts both defined to
+nothing usages (CrOS EC `config.h` style), and defined to `1` usages (Zephyr
+Kconfig style).
+
+However, long term, we may find this to be a continual cause of issues, and
+creating hacks for every colliding macro or function may be unsustainable. We
+propose _gradually_ introducing a namespace prefix to the `platform/ec`
+codebase, for example `crec_`. We can begin at the critical areas of namespace
+collision (e.g., atomics) and continue to improve the naming convention with
+time.
+
+### New CQ check
+
+As long as code from platform/ec is part of the zephyr
+[ebuild](http://cs/chromeos_public/src/third_party/chromiumos-overlay/chromeos-base/chromeos-zephyr-2_3/chromeos-zephyr-2_3-9999.ebuild),
+then we need to run the Zephyr CQ checks on any platform/ec CLs in addition to
+the normal platform/ec CQ checks. This ensures that platform/ec changes aren’t
+breaking the Zephyr builds and requiring the Zephyr team to debug recent
+changes.
+
+For local builds, we can run `emerge-betty chromeos-zephyr-2_3` or `zmake`
+utility to check that an EC CL has not broken anything on the Zephyr side.
+
+We will work with the CI team to enable this.
+
+## How to shim features
+
+Before you get started shimming a feature, it's important to
+understand the general philosophies behind Zephyr OS and shimming:
+
+* Our current EC's OS isn't going away any time soon. Even after we
+ ship our first device with a Zephyr-based EC, we may still be working on
+ other projects using the old OS. It's important to consider how
+ your feature will apply to both the Zephyr world and CrOS EC OS
+ world.
+
+* We won't be converting old devices to use Zephyr-based firmware.
+ This means that our existing OS and its code will need maintained
+ for bug and security fixes for years to come. **Do not allow the
+ code you write for the CrOS EC OS to lack in quality or be "throw
+ away code" as it will need to be maintained for a long time.**
+
+* Shimming, by the very nature of the design, will lead to some ugly
+ hacks. We try and avoid this when we can, but some of them may be
+ completely unavoidable. This means we need to actively work against
+ nature to keep the code clean. If we do things right, there's even
+ a possibility that we leave things cleaner than we found them.
+
+* Shimming occasionally digs up landmines. Be prepared to step on
+ them. 💣
+
+### What code can be shimmed?
+
+Code in the `common/` directory (and other common code directories,
+like `power/`) is the ideal target for shimming, with the exception of
+core OS features which have Zephyr OS equivalents.
+
+Code in the following directories should **never be shimmed**:
+
+- `core/`: this directory contains architecture-specific code which
+ should have a Zephyr OS equivalent feature.
+
+- `chip/`: this directory contains chip-specific code, and similarly
+ should have a Zephyr OS equivalent feature.
+
+In both cases, you should instead determine (or, in rare cases,
+implement upstream) the equivalent Zephyr OS feature, and *implement
+an architecture and chip agnostic* "shim layer" in the `zephyr/shim/`
+directory which translates the APIs as necessary.
+
+As of the time of this document, the shim layer is nearing 100%
+complete, and it should be rare that you encounter an API which needs
+translation.
+
+Finally, code in the following directories should **avoid being
+shimmed, if possible**:
+
+- `board/`: this directory contains variant-specific code.
+
+- `baseboard/`: this directory contains baseboard-specific code.
+
+In both cases, the only value in shimming in code from one of those
+directories would be to enable a Zephyr OS build for a device which
+already has CrOS EC OS support, as *Zephyr-only projects will not have
+these directories*. You should be thinking about how this would be
+implemented for a Zephyr-only project, and filing bugs to create the
+appropriate device-tree and Kconfig equivalents before shimming this
+code.
+
+See [Zephyr PoC device bringup](zephyr_poc_device_bringup.md) for more
+information about bringing up proof-of-concept devices.
+
+### Configuration
+
+CrOS EC OS uses a special header `config.h`, which sets configuration
+defaults, and includes board and chip specific configurations by
+expecting the headers `board.h` and `config_chip.h` to be present.
+Most of these configuration options start with `CONFIG_`, however the
+rules were loosely defined over the years.
+
+Zephyr OS, on the other hand, uses two different configuration
+systems:
+
+* Kconfig, the configuration system from the Linux Kernel, which
+ fits well within the domain of preprocessor definitions in C. The
+ schema for our Kconfig files can be found under `zephyr/Kconfig`,
+ and project-specific configurations are made in `prj.conf` files.
+
+ Kconfig is generally used to select which EC software features are
+ enabled, and should be avoided for hardware configurations, such as
+ chip configuration registers and their default settings.
+
+* Open Firmware Device Tree, which you may also be familiar with from
+ the Linux kernel. This configuration can be found in `*.dts` files.
+
+ Device-tree is generally used for hardware configurations, and
+ should be avoided for EC software feature configuration.
+
+For code which is shimmed, we need to play nicely with both the CrOS
+EC OS configuration system, and Zephyr's configuration systems. Thus,
+we follow the following pattern:
+
+* EC software features are configured using `Kconfig` and
+ `zephyr/shim/include/config_chip.h` translates them into the
+ appropriate CrOS EC OS configurations using patterns such as below:
+
+ ```c
+ #undef CONFIG_CMD_GETTIME
+ #ifdef CONFIG_PLATFORM_EC_TIMER_CMD_GETTIME
+ #define CONFIG_CMD_GETTIME
+ #endif
+ ```
+
+ The preprocessor code should follow that template exactly, and not
+ use any nesting (Kconfig handles dependencies, there is no reason to
+ do it again in the preprocessor code).
+
+* **The domain of Kconfig options and CrOS EC configuration names
+ should be completely distinct.** This is because the Kconfig options
+ are included automatically, and including `config.h` may undefine
+ them. To mitigate this, we follow a convention of using
+ `CONFIG_PLATFORM_EC_` as the prefix for EC software features in
+ Kconfig.
+
+One special configuration option exists, `CONFIG_ZEPHYR`, which you
+can use to detect whether the OS is Zephyr OS. This is the
+conventional way to add Zephyr-specific (or excluded) code in CrOS EC
+code.
+
+The typical EC macros for reducing `#ifdef` messes (e.g.,
+`IS_ENABLED`, `STATIC_IF`, etc.) work with both CrOS EC OS and Kconfig
+options, and should be used when possible.
+
+### Header Files
+
+Besides the include paths provided by Zephyr OS, the following paths
+are additionally added for shimmed code:
+
+* `include/`
+* `zephyr/include/`
+* `zephyr/shim/include/`
+
+The names of headers in these directories should be completely
+distinct. C compilers have no mechanism for "include ordering", and
+there is no way to "override a header".
+
+If you feel the need to "override" a header, say `foo.h` in
+`include/`, the best way to do this is to give it a different name
+under `zephyr/shim/include` (e.g., `zephyr_foo_shim.h`), and include
+that in the `foo.h` header with a `#ifdef CONFIG_ZEPHYR` guard.
+
+The typical styling convention for includes (following existing
+conventions in `platform/ec` and other C codebases we have) is:
+
+* Zephyr OS headers in pointy brackets, in alphabetical order.
+
+* One blank line
+
+* CrOS EC OS headers (either from `include/`, `zephyr/shim/include/`,
+ or the current directory), in quotes (not pointy brackets).
+
+### Adding files to Cmake
+
+Zephyr's build system (including shimmed code) uses CMake instead of
+`Makefiles`, and your code will not be compiled for Zephyr unless you
+list the files in `zephyr/CMakeLists.txt`.
+
+### Step-by-step guide to adding a Kconfig
+
+Follow these steps:
+
+1. Make sure you have read the above Configuration section
+
+2. Add your config to one of zephyr/Kconfig* files. Note the PLATFORM_EC_ prefix
+ and try to put it near related things:
+
+ ```kconfig
+ config PLATFORM_EC_CHARGER_BQ25720
+ bool "TI BQ25720 charger"
+ help
+ The TI BQ25720 is a blah blah (describe summary from datasheet,
+ at least 3 lines so take 10 minutes to write something truly useful)
+ ```
+
+ Consider a `depends on PLATFORM_EC_...` line if it depends on an existing
+ feature.
+
+3. Add to zephyr/shim/include/config_chip.h (put it at the bottom):
+
+ ```kconfig
+ #undef CONFIG_CHARGER_BQ25720
+ #ifdef CONFIG_PLATFORM_EC_CHARGER_BQ25720
+ #define CONFIG_CHARGER_BQ25720
+ #endif
+ ```
+
+4. Add the source file to zephyr/CMakeLists.txt if it is not already there. For
+ ordering check the comments in that file:
+
+ `zephyr_sources_ifdef(CONFIG_PLATFORM_EC_CHARGER_BQ25720
+ "${PLATFORM_EC}/driver/charger/bq25720.c")`
+
+5. Run a build on a board that enables the new CONFIG (in config.h) to make sure
+ there are no problems.
+
+6. If it doesn't work, please email zephyr-task-force@ or file a bug and assign
+ it to sjg@, cc zephyr-task-force@ (please include CL link and the error
+ output).
+
+### Unit Tests
+
+Unit tests, implemented using the Ztest framework, can be found in
+`zephyr/test`.
+
+To run all unit tests, you use `zmake testall`.
+
+## Alternatives Considered
+
+### Translate code and mirror into the zephyr-chrome repository
+
+We could potentially write a script which, via a series of find/replace
+operations, translates a platform/ec module to use Zephyr functions, macros, and
+paradigms. On a frequent basis, we would translate all modules of interest in
+the platform/ec repository and land an "uprev" change in the zephyr-chrome
+repository.
+
+The main disadvantage of this technique is that we can't get any CQ coverage
+when platform/ec CLs land that the modules will continue to work in Zephyr.
+Additionally, the translator script would be delicate and probably require
+frequent maintenance.
+
+However, this technique does have some benefits. With modules directly
+translated to code in the Zephyr paradigm, the process of upstreaming a shimmed
+module to ZephyrOS would be significantly easier. Additionally, it would require
+no shim code in platform/ec.
+
+### Don't do any code sharing
+
+One option is to avoid shimming in any platform/ec code and allow the Zephyr
+team to re-implement features in upstream zephyr, or our local zephyr-chrome
+repository.
+
+Disregarding the infeasible amount of work required to complete this option, the
+platform/ec repository has a far faster development pace as there are many more
+contributors, and the Zephyr features would quickly lose parity during the time
+frame that we are launching both Zephyr-based and platform/ec-based devices.