summaryrefslogtreecommitdiff
path: root/docs/zephyr/project_config.md
blob: f930908502c4375c3491e02702832b959357f036 (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
Project Configuration
=====================

[TOC]

## Setting up a new program ("reference board" or "baseboard")

Unlike the legacy EC codebase, Zephyr projects all live together in
one big happy directory.  The intent of this design is to encourage
code-sharing between projects, and reduce the amount of copy/paste
that is required to bring up a new project.  This directory can, but
does not have to, correlate to the unified build Chrome OS board,
however firmware authors can always choose a different structure if it
makes sense for the specific scenario.  As a hypothetical example,
similar Chromeboxes and Chromebooks may wish to share the Zephyr EC
project directory instead of use separate directories, even if they
are using a different unified build board.

To set up a new EC program, create a new directory under
[`zephyr/projects`](../../zephyr/projects) with the following files:

- `BUILD.py` - specifies which builds can be made from this directory,
  and what the device-tree overlays and Kconfig files are for each
  build.
- `CMakeLists.txt` - Baseboard-specific C files can be listed here.
- `prj.conf` (optional) - Default Kconfig settings for all projects.
- `Kconfig` (optional) - Set options for your reference design here,
  which variants can use to install optional C sources.

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 Zephyr board to use for
  the project.  The Zephyr build system expects a Zephyr board
  directory under `boards/${ARCH}/${ZEPHYR_BOARD_NAME}`.  **Note:**
  the concept of a Zephyr board does not align with the Chrome OS
  concept of a board: for most projects this will typically be the
  name of the EC chip used, not the name of the model or overlay.
- `supported_toolchains` (required): A list of the toolchain names
  supported by the build.  Valid values are `coreboot-sdk`, `host`,
  `llvm`, and `zephyr`.  Note that only `coreboot-sdk` and `llvm` are
  supported in the chroot, and all projects must be able to build in
  the chroot, so your project must at least list one of `coreboot-sdk`
  or `llvm`.
- `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.
  Defaults to no overlays (empty list).
- `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(ec)
```

You may additionally want to specify any C files your project needs
using `zephyr_library_sources`. If you need to add extra include
directories, use `cros_ec_library_include_directories`.

### prj.conf and prj_${project_name}.conf

`prj.conf` has default Kconfig settings for all projects, and
`prj_${project_name}.conf` can contain overrides for certain projects.
The format is `KEY=VALUE`, as typical for Kconfig.

### 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.

## 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.