summaryrefslogtreecommitdiff
path: root/docs/zephyr/project_config.md
blob: f81cc083c93634d1005f0ae49f0ba8d13a63d31a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
Project Configuration
=====================

[TOC]

## Overview

This document defines the organization of the program and project specific files
needed by Zephyr EC projects.

The goals of the project organization include:

* Minimize code duplication, allowing multiple projects to share common
  configuration options and devicetree nodes.
* Define the set of files required by each project.
* Define the best practices for devicetrees.


### Glossary

- **program**: The name of a Chromebook reference design. The **program**
  includes all Chromebooks based on a single AP SoC, such as Intel MeteorLake,
  Qualcomm 7c G3, or AMD Mendocino. The **program** corresponds to a single
  board overlay in the ChromeOS SDK.  The term *baseboard* is often used as a
  synonym for **program**.

- **project**: The name of a specific Chromebook model or variant.  All
  Chromebook **programs** contain at least one **project** which serves as the
  reference design(s) for the **program**. The reference **project** may or may
  not use the same name as the **program**. For example, the reference
  **project** for the skyrim **program** is also called skyrim. The corsola
  **program** included two reference **projects**, kingler and krabby. For the
  legacy ECOS builds, *board* was used as a synonym for **project**.

This document uses bold to highlight the terms **program** and **project** to
reference the definitions above.

## Directory Structure

The [`zephyr/program`](../../zephyr/program) contains the **program** and
**project** configuration files for all Zephyr based EC builds.

### `zephyr/program` directory

Each **program** has it's own subdirectory under `zephyr/program`.

```
zephyr/program/
├── brya/
├── corsola/
├── herobrine/
├── intelrvp/
├── it8xxx2_evb/
├── minimal/
├── nissa/
├── npcx_evb/
├── rex/
├── skyrim/
└── trogdor/
```

> The [`zephyr/program/minimal`](../../zephyr/program/minimal/) **program**
contains example EC projects that demonstrate how to build a Zephyr EC with the
minimum feature set enabled. These projects require only a working UART on the
target board.

### `zephyr/program/`**`<program>`**`/` Directory Overview

Each **program** subdirectory contains a subdirectory foreach each **project**,
including a subdirectory for the reference **project**.

The minimum configuration for a **program** named *skyrim* with just a single
reference **project**, also named *skyrim*, is shown below.

```
zephyr/program/skyrim/
├── include/
│   └── <program headers>.h
├── skyrim/
│   ├── include/
│   │   └── <project headers>.h
│   ├── src/
│   │   └── <project sources>.c
│   ├── CMakeLists.txt
│   ├── project.conf
│   └── project.overlay
├── src/
│   └── <program sources>.c
├── BUILD.py
├── CMakeLists.txt
├── Kconfig
├── program.conf
└── <devicetrees>.dtsi
```

#### `zephyr/program/`**`<program>`**`/` Directory Details

Description of the files and directories found directly in the **<program>**
level directory. Note that all paths are relative to the `zephyr/program/`
directory.

- **`<program>`**`/`: Top level directory for the **program**. [skyrim] is the
  *program* name in the example above.
- **`<program>`**`/include/`: Directory containing the header files common to
  all **projects** in the **program**. Use of **program** level includes is
  discouraged.  Instead, consider creating a generic driver that can be shared
  across all **programs**.
- **`<program>`**`/src/`: Directory containing the C source files common to all
  **projects** in the **program**.
- [**`<program>`**`/BUILD.py`](#build_py): Defines which **projects** can be
  made from this directory.
- [**`<program>`**`/CMakeLists.txt`](#cmakelists_txt): CMake file for the
  **program**.
- [**`<program>`**`/Kconfig`](#kconfig) - Defines new Kconfig options, used by
  all **projects** in the **program**.
- [**`<program>`**`/program.conf`](#program_conf) - Sets the default Kconfig
  settings for all **projects**.
- **`<program>`**`/<devictrees>.dtsi` - One or more devicetree files, organized
  by the hardware module or EC feature.  See the [Devicetree Best
  Practices](#devicetree-best-practices) section for additional information.
- **`<program>`**`/`**`<project>`**`/`: Top level directory for the
  **<project**>. Create a separate directory for each **project** defined by the
  **program**.

### `zephyr/program/`**`<program>`**`/`**`<project>`**`/` Directory Details

Each **project** provides the following files. Note that all paths are relative
to the `zephyr/program/`**`<program>`**`/` directory.

- **`<project>`**`/include/`: The **project** may optionally provide a public
  include directory, but this is discouraged. There are some exceptions where
  the legacy EC code expects the project to define a public header, such as the
  keyboard_customization.h file.
- **`<project>`**`/src/`: Directory containing the C source files specific to
  the **project**.
- [**`<project>`**`/CMakeLists.txt`](#cmakelists_txt): CMake file for the
  **project**.
- [**`<project>`**`/project.conf`](#project_conf): Kconfig settings for the
  **project**.
- [**`<project>`**`/project.overlay`](#project_overlay): Main devicetree overlay
  for the **project**.

Creation of custom C source files specific to the **program** or **project** is
discouaraged. You can usually project manage project specific settings with
Kconfig and devicetree changes only.

Note that **program** and **project** custom C files are still subject to the
same unit test requirements. So all custom C files also require that you write
tests.

## Setting up a new **program**

To set up a new EC **program**, create a new directory under
[`zephyr/program`] with the organization shown below.
Note that for this example, the new **program** is called "my_program", and the
reference **project** is called "my_reference_project".

> Tip - Copy one the **projects** defined by the [*minimal*] **program** to
> start with the bare miminimum of features required to boot the Zephyr EC
> appliation. Then follow the steps in the detailed in [Creating a New Zephyr EC
> Project].

```
zephyr/program/my_program/
├── my_reference_project/
│   ├── CMakeLists.txt
│   ├── project.conf
│   └── project.overlay
├── BUILD.py
├── CMakeLists.txt
├── Kconfig
└── program.conf
```

An in-depth example of each file is given below:

### BUILD.py

`BUILD.py` is a Python-based config file for setting up your reference
board and the associated variants.  The name `BUILD.py` is important
and case-sensitive: `zmake` searches for files by this
name.

When `BUILD.py` is sourced, the following two globals are defined:

- `here`: A `pathlib.Path` object containing the path to the directory
  `BUILD.py` is located in.
- `register_project`: A function which informs `zmake` of a new
  project to be built.  Your `BUILD.py` file needs to call this
  function one or more times.

`register_project` takes the following keyword arguments:

- `project_name` (required): The name of the project (typically the
  Google codename).  This name must be unique amongst all projects
  known to `zmake`, and `zmake` will error if you choose a conflicting
  name.
- `zephyr_board` (required): The name of the EC chip used. **Note:** the concept
  of a Zephyr board does not align with the ChromeOS concept of a board. The
  Zephyr build system requires a set of devicetree and Kconfig files under under
  `boards/${ARCH}/${ZEPHYR_BOARD_NAME}`. For the Zephyr EC application, the EC
  chip is mapped onto the Zephyr board organization. Supported `zephyr_boards`
  include:
   - `mec1727`: Microchip MEC1727, 416 KiB RAM, 512 KiB flash
   - `npcx7`: Nuvoton NPCX7m7FC, 384 KiB, 512 KiB flash
   - `npcx9m3f`: Nuvoton NPCX9m3F, 320 KiB RAM, 512 KiB flash
   - `npcx9m7f`: Nuvoton NPCX9m7F, 384 KiB RAM, 1 MiB flash
   - `it81202bx`: ITE IT81202, 60 KiB RAM, 1 MiB flash
   - `it81302bx`: ITE IT81302, 60 KiB RAM, 1 MiB flash
- `supported_toolchains` (required): A list of the toolchain names
  supported by the build.  Valid values are:
  - `coreboot-sdk`: only supported in the chroot
  - `host`: used for unit and integration tests
  - `llvm`: only supported in the chroot
  - `zephyr`: only supported outside the chroot
- `output_packer` (required): An output packer type which defines
  which builds get generated, and how they get assembled together into
  a binary.
- `modules` (optional): A list of module names required by the
  project.  The default, if left unspecified, is to use all modules
  known by `zmake`.  Generally speaking, there is no harm to including
  unnecessary modules as modules are typically guarded by Kconfig
  options, so the only reason to set this is if your project needs to
  build in a limited environment where not all modules are available.
- `is_test` (optional): `True` if the code should be executed as a
  test after compilation, `False` otherwise.  Defaults to `False`.
- `test_args` (optional): A list of command line arguments that should
  be used when running the test.  Instances of `{test_temp_dir}`
  inside of an argument will be replaced with a path to a temporary
  directory guaranteed to be unique for the current execution.
- `dts_overlays` (optional): A list of files which should be concatenated
  together and applied as a Zephyr device-tree overlay. The recommended setting
  is to select the **project** specific devicetree overlay file.

    ``` python
    dts_overlays=[here / project_name / "project.overlay"]
    ```

- `kconfig_files` (optional): A list of files that contain the Kconfig settings
  for the **project**. The recommended setting is select the **program**
  configuration file followed by the **project** configuration file.

    ``` python
    kconfig_files=[here / "program.conf", here / <project> / "project.conf",]
    ```

- `project_dir` (optional): The path to where `CMakeLists.txt` and
  `Kconfig` can be found for the project, defaulting to `here`.

Note that most projects will not want to call `register_project`
directly, but instead one of the helper functions, which sets even
more defaults for you:

- `register_host_project`: Define a project which runs in the chroot
  (not on hardware).
- `register_host_test`: Just like `register_host_project`, but
  `is_test` gets set to `True`.
- `register_raw_project`: Register a project which builds a single
  `.bin` file, no RO+RW packing, no FMAP.
- `register_binman_project`: Register a project which builds RO and RW
  sections, packed together, and including FMAP.
- `register_npcx_project`: Just like `register_binman_project`, but
  expects a file generated named `zephyr.npcx.bin` for the RO section
  with Nuvoton's header.

You can find the implementation of these functions in
[`zephyr/zmake/zmake/configlib.py`](../../zephyr/zmake/zmake/configlib.py).

`BUILD.py` files are auto-formatted with `black`.  After editing a
`BUILD.py` file, please run `black BUILD.py` on it.

### CMakeLists.txt

This file, should at minimum contain the following:

``` cmake
cmake_minimum_required(VERSION 3.20.1)

find_package(Zephyr REQUIRED HINTS "${ZEPHYR_BASE}")
project(**project**)
```

If your **program** provides any C files, add them to your program CMake file
using `zephyr_library_sources()`.

``` cmake
zephyr_library_sources("src/my_program_source.c")
```

For your **project** C files, create **`<project>/`**`CMakeLists.txt` and use
`add_subdirectory()` to include the **project** CMake file.

``` cmake
add_subdirectory("my_reference_project")
```

Add the requires `zephyr_library_souces()` calls to the
**`<project>/`**`CMakeLists.txt` file.

If your **program** or **project** provides a public header, make the include
directory visible to rest of the code using
`cros_ec_library_include_directories()`.

``` cmake
cros_ec_library_include_directories("include")
```

### Kconfig

If certain projects need project-specific C files or ifdefs, the only
way to do so is to create a `Kconfig` file with the options schema you
want, and use it to toggle the inclusion of certain files.

The file must end with a single line that reads
`source "Kconfig.zephyr"`.  Note that this file is optional, so it's
recommended to only include it if you really need it.

### program.conf

`program.conf` has default Kconfig settings for all **projects** defined for the
**program**. The format is `KEY=VALUE`, as typical for Kconfig.

### project.conf

`project.conf` has the Kconfig settings for a single **project**. The format is
`KEY=VALUE`, as typical for Kconfig.

Kconfig settings in `project.conf` take precedence over the Kconfig settings
from `program.conf`.

### project.overlay

`project.overlay` is the main devicetree overlay for the **project**. The
`project.overlay` contains the following components:
- One or more `#include` statements to add devicetrees defined by the
  **program** into project.
- `/delete-node/` statements to remove specific devicetree nodes defined by the
  **program** devicetrees.
- New devicetree nodes for **project** specific settings that are not provided
  by any **program** devicetrees.

> Tip: After building your **project**, you can view the final devicetree in the
file `build/zephyr/`**`<project>`**`/build-ro/zephyr/zephyr.dts`.

## Setting up a new variant of an EC program

**Unlike our legacy EC, there are no files or directories to copy and
paste to setup a new variant in Zephyr code.**

Simply add a `register_project`-based call to the existing `BUILD.py`
for your reference board.

Below is an example of how programs may wish to structure this in
`BUILD.py`:

``` python
# Copyright 2021 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

def register_variant(project_name, chip="it8xx2", extra_dts_overlays=()):
    return register_binman_project(
        project_name=project_name,
        zephyr_board=chip,
        dts_overlays=[
            here / "base_power_sequence.dts",
            here / "i2c.dts",
            **extra_dts_overlays,
        ],
    )


# Reference board
register_variant(
    project_name="asurada",
    extra_dts_overlays=[here / "reference_gpios.dts"],
)

# Variants
register_variant(
    project_name="hayato",
    extra_dts_overlays=[here / "hayato_gpios.dts"],
)
```

If a project is going to be a simple variant of another project (e.g.,
project `bar` is exactly identical to project `foo` but has just a few
device-tree/Kconfig changes), you can spin a new variant using the
return value of the register functions:

``` python
foo = register_variant(project_name="foo")
bar = foo.variant(
    project_name="bar",
    dts_overlays=[here / "bar_extras.dts"],
)
```

With this simple variant syntax, lists (like Kconfig files and DTS
overlays) are concatenated.  This means it's not possible to remove
files during variant registration for this syntax, so it's only
recommended for the simple case.

## Devicetree Best Practices

Below are the best practices for devicetree organization:

* Split the devicetree across multiple files, organized by the functional block.
  This organization applies to the shared **program** devicetrees only.
  * FW_CONFIG
  * GPIOs
  * I2C
  * Interrupts
  * Keyboard
  * LEDs
  * Sensors
  * Thermal (fans and temperature sensors)
  * USB-C
* When creating **program**, usually with a single reference project, add the
  shared devicetree files in the program directory, separated by the functional
  area noted above.
* Each project creates a `project.overlay` file, and uses `#include` statements
  to add shared devicetree files from the program directory. An example
  project.overlay for the skyrim project is shown below.

  ``` c
  /* Copyright 2021 The ChromiumOS Authors
   * Use of this source code is governed by a BSD-style license that can be
   * found in the LICENSE file.
   */

  /* Skyrim program common DTS includes */
  #include "../adc.dtsi"
  #include "../fan.dtsi"
  #include "../gpio.dtsi"
  #include "../i2c.dtsi"
  #include "../interrupts.dtsi"
  #include "../keyboard.dtsi"
  #include "../motionsense.dtsi"
  #include "../usbc.dtsi"

  /* Skyrim project node overrides */
  /* ... */
  ```

### Managing **project** specific settings

When the **project** needs to make changes to the shared devicetree files, there
are two strategies:

* For small changes, add the `/delete-node/` attribute to the `project.overlay`
  file to remove the specific devices and devicetree nodes from the **project**
  final devicetree.
* For larger changes, remove the corresponding `#include` statements from the
  `project.overlay` file. Then,dDirectly add any required nodes to the
  `project.overlay` file.

In both cases, the shared devicetree file in the **program** directory is not
changed.

### Small Devicetree Changes

Examples of small devicetree changes include:
* Change the I2C peripheral address of a device.
* Changing USB-C related chips.
* Changing motionsense properties, such as the odr and ec-rate properties.
* Overriding a specific property of a node - for instance modifying the
  `pinctrl-0` property to adjust the EC pins connected to a device driver.

The example below demonstrates how to define a device in a **program**
devicetree file and then override the setting in the `project.overlay` file.

* The herobrine program defines the TCPC at I2C address `0xb` in the file
`zephyr/program/herobrine/i2c.dtsi`. This I2C address is valid for the
herobrine, evoker, and villager projects while the hoglin project needs to
change the I2C address to `0x1b`.

  ``` c
  /* zephyr/program/herobrine/i2c.dtsi */

  &i2c1_0 {
    status = "okay";
    /* ... */
    tcpc_port0: ps8xxx@b {
      compatible = "parade,ps8xxx";
      reg = <0xb>;
    };
  };
  ````
* The hoglin `project.overlay` file deletes the TCPC node at address `0xb` and
creates a new node at address `0x1b`.  The node name “tcpc_port0” is kept the
same, so any references to this node name do not change, such as the USB-C port
configuration.

  ``` c
  /* zephyr/program/herobrine/hoglin/project.overlay */

  #include “../i2c.dtsi”

  &i2c1_0 {
    /delete-node/ ps8xxx@b;
    tcpc_port0: ps8xxx@1b {
      compatible = "parade,ps8xxx";
      reg = <0x1b>;
    };
  };
  ```

While it is also possible to change a device’s I2C address by directly
overriding the `reg` property, this should not be done. Changing only the `reg`
property causes a mismatch between the node name, `ps8xxx@b`, and the actual
device address, `0x1b`.

Your `project.overlay` file can also directly override properties defined by the
**program** devicetree files.

* The skyrim **program** sets the I2C clock frequency for first I2C bus to fast
  (400 KHz).
  ``` c
  /* zephyr/program/skyrim/i2c.dtsi */
  &i2c0_0 {
    status = "okay";
    label = "I2C_TCPC0";
    clock-frequency = <I2C_BITRATE_FAST>;
    pinctrl-0 = <&i2c0_0_sda_scl_gpb4_b5>;
    pinctrl-names = "default";
  };
  ```
* Override the I2C clock frequency to fast-plus (1 MHz) in the winterhold
  `project.overlay`.
  ``` c
  /* zephyr/program/skyrim/winterhold/project.overlay */
  #include "../i2c.dtsi"
  &i2c0_0 {
    clock-frequency = <I2C_BITRATE_FAST_PLUS>;
  };
  ```
### Large Devicetree Changes

For large devicetree changes, the preference is to copy the relevant devicetree
fragment into the `project.overlay` file and edit the fragment directly.

Examples of large devicetree changes (or changes that don’t benefit from using
the /delete-node/ attribute) include:
* GPIOs - specifically the “named-gpios” node.  This integrates better with the
  arbitrage and the pinmap utility, which auto-generates the EC GPIO settings
  based on schematic data.
* Changes to the motionsense sensor types.  Currently x86 architectures impose a
  fixed ordering for the accelerometers and gryoscopes when accessed through the
  LPC memory map (see the [`EC_MEMMAP_ACC_DATA`]). Deleting nodes changes the
  order of the children under the motionsense-sense node and causes the test
  [`hardware.SensorAccel`] to fail. Copy the motionsense nodes into the
  project.overlay file and modify as required.
* LED policies - generally each OEM/ODM defines unique LED policies for their
  designs to establish differentiation for their brand. There is little value to
  creating common LED policies for all **projects** in the **program**.
* Batteries - batteries also are generally specific to the OEM/ODM. Define the
  **project** batteries directly in the `project.overlay` file.


[skyrim]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/HEAD:src/platform/ec/zephyr/program/skyrim
[`zephyr/program`]: ../../zephyr/program/
[*minimal*]: ../../zephyr/program/minimal/
[Creating a New Zephyr EC Project]: ./zephyr_new_board_checklist.md
[`EC_MEMMAP_ACC_DATA`]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/HEAD:src/platform/ec/include/ec_commands.h;l=181
[`hardware.SensorAccel`]: https://crsrc.org/o/src/platform/tast-tests/src/chromiumos/tast/local/bundles/cros/hardware/sensor_accel.go;drc=8fbf2c53960bc8917a6a01fda5405cad7c17201e;l=30