diff options
Diffstat (limited to 'docs/zephyr_shim.md')
-rw-r--r-- | docs/zephyr_shim.md | 381 |
1 files changed, 0 insertions, 381 deletions
diff --git a/docs/zephyr_shim.md b/docs/zephyr_shim.md deleted file mode 100644 index fac0383aff..0000000000 --- a/docs/zephyr_shim.md +++ /dev/null @@ -1,381 +0,0 @@ -[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. |