Tom Hughes | 80ea7fa | 2019-06-11 21:02:40 | [diff] [blame] | 1 | # Embedded Controller (EC) |
| 2 | |
| 3 | [TOC] |
| 4 | |
Keith Short | 76f3945 | 2022-02-18 19:49:11 | [diff] [blame] | 5 | > **Note** - This document covers the legacy Chrome EC implementation. The |
| 6 | > legacy EC implementation is used by all Chromebook reference designs prior to |
| 7 | > July 2021. On newer Chromebook designs, the EC implementation is based on the |
| 8 | > Zephyr RTOS. Refer to the [Zephyr EC Introduction](./docs/zephyr/README.md) |
| 9 | > for details on the Zephyr EC implementation. |
| 10 | |
Tom Hughes | 80ea7fa | 2019-06-11 21:02:40 | [diff] [blame] | 11 | ## Introduction |
| 12 | |
| 13 | The Chromium OS project includes open source software for embedded controllers |
| 14 | (EC) used in recent ARM and x86 based Chromebooks. This software includes a |
| 15 | lightweight, multitasking OS with modules for power sequencing, keyboard |
| 16 | control, thermal control, battery charging, and verified boot. The EC software |
Tom Hughes | 2f40b71 | 2021-01-26 18:38:55 | [diff] [blame] | 17 | is written in C and supports |
Dossym Nurmukhanov | 7d9a425 | 2021-02-02 05:45:38 | [diff] [blame] | 18 | [a variety of micro-controllers](https://chromium.googlesource.com/chromiumos/platform/ec/+/main/chip/). |
Tom Hughes | 80ea7fa | 2019-06-11 21:02:40 | [diff] [blame] | 19 | |
| 20 | This document is a guide to help make you familiar with the EC code, current |
| 21 | features, and the process for submitting code patches. |
| 22 | |
| 23 | For more see the Chrome OS Embedded Controller |
| 24 | [presentation](https://docs.google.com/presentation/d/1Xa_Z6SjW-soPvkugAR8__TEJFrJpzoZUa9HNR14Sjs8/pub?start=false&loop=false&delayms=3000) |
| 25 | and [video](http://youtu.be/Ie7LRGgCXC8) from the |
| 26 | [2014 Firmware Summit](http://dev.chromium.org/chromium-os/2014-firmware-summit). |
| 27 | |
| 28 | ## What you will need |
| 29 | |
| 30 | 1. A Chromebook with a compatible EC. This includes the Samsung Chromebook |
| 31 | (XE303C12) and all Chromebooks shipped after the Chromebook Pixel 2013 |
| 32 | (inclusive). See the |
| 33 | [Chrome OS devices](http://dev.chromium.org/chromium-os/developer-information-for-chrome-os-devices) |
| 34 | page for a list. |
Aseda Aboagye | 1b5a84c | 2021-04-09 21:45:58 | [diff] [blame] | 35 | 1. A Linux development environment. The latest Debian Stable (x86_64) is commonly used. |
| 36 | Linux in a VM may work if you have a powerful host machine. |
Tom Hughes | 80ea7fa | 2019-06-11 21:02:40 | [diff] [blame] | 37 | 1. A [servo debug board](http://dev.chromium.org/chromium-os/servo) (and |
| 38 | header) is highly recommended for serial console and JTAG access to the EC. |
| 39 | 1. A sense of adventure! |
| 40 | |
Tom Hughes | 6f76b0a | 2019-06-13 18:24:19 | [diff] [blame] | 41 | ## Terminology |
| 42 | |
| 43 | ### EC |
| 44 | |
| 45 | EC (aka Embedded Controller) can refer to many things in the Chrome OS |
| 46 | documentation due to historical reasons. If you just see the term "EC", it |
| 47 | probably refers to "the" EC (i.e. the first one that existed). Most Chrome OS |
| 48 | devices have an MCU, known as "the EC" that controls lots of things (key |
| 49 | presses, turning the AP on/off). The OS that was written for "the" EC is now |
Tom Hughes | 2f40b71 | 2021-01-26 18:38:55 | [diff] [blame] | 50 | running on several different MCUs on Chrome OS devices with various tweaks (e.g. |
| 51 | the FPMCU, the touchpad one that can do palm rejection, etc.). It's quite |
Tom Hughes | 6f76b0a | 2019-06-13 18:24:19 | [diff] [blame] | 52 | confusing, so try to be specific and use terms like FPMCU to distinguish the |
| 53 | fingerprint MCU from "the EC". |
| 54 | |
Keith Short | 0596ecd | 2019-08-13 23:07:04 | [diff] [blame] | 55 | See the [EC Acronyms and Technologies](./docs/ec_terms.md) for a more complete |
| 56 | glossary. |
| 57 | |
Tom Hughes | 80ea7fa | 2019-06-11 21:02:40 | [diff] [blame] | 58 | ## Getting the EC code |
| 59 | |
| 60 | The code for the EC is open source and is included in the Chromium OS |
| 61 | development environment (`~/trunk/src/platform/ec/</code>`). |
| 62 | See[ http://www.chromium.org/chromium-os/quick-start-guide](http://dev.chromium.org/chromium-os/quick-start-guide) |
| 63 | for build setup instructions. If you want instant gratification, you can fetch |
| 64 | the source code directly. However, you will need the tool-chain provided by the |
| 65 | Chromium OS development environment to build a binary. |
| 66 | |
| 67 | ```bash |
| 68 | git clone https://chromium.googlesource.com/chromiumos/platform/ec |
| 69 | ``` |
| 70 | |
Keith Short | f634e7c | 2019-08-20 22:50:13 | [diff] [blame] | 71 | The source code can also be browsed on the web at: |
Tom Hughes | 80ea7fa | 2019-06-11 21:02:40 | [diff] [blame] | 72 | |
| 73 | https://chromium.googlesource.com/chromiumos/platform/ec/ |
| 74 | |
| 75 | ## Code Overview |
| 76 | |
| 77 | The following is a quick overview of the top-level directories in the EC |
| 78 | repository: |
| 79 | |
Keith Short | f634e7c | 2019-08-20 22:50:13 | [diff] [blame] | 80 | **baseboard** - Code and configuration details shared by a collection of board |
| 81 | variants. Tightly linked with the `board` directory described below. |
| 82 | |
Tom Hughes | 80ea7fa | 2019-06-11 21:02:40 | [diff] [blame] | 83 | **board** - Board specific code and configuration details. This includes the |
| 84 | GPIO map, battery parameters, and set of tasks to run for the device. |
| 85 | |
| 86 | **build** - Build artifacts are generated here. Be sure to delete this and |
| 87 | rebuild when switching branches and before "emerging" (see Building an EC binary |
| 88 | below). make clobber is a convenient way to clean up before building. |
| 89 | |
| 90 | **chip** - IC specific code for interfacing with registers and hardware blocks |
| 91 | (adc, jtag, pwm, uart etc…) |
| 92 | |
| 93 | **core** - Lower level code for task and memory management. |
| 94 | |
| 95 | **common** - A mix of upper-level code that is shared across boards. This |
| 96 | includes the charge state machine, fan control, and the keyboard driver (among |
| 97 | other things). |
| 98 | |
| 99 | **driver** - Low-level drivers for light sensors, charge controllers, |
| 100 | I2C/onewire LED controllers, and I2C temperature sensors. |
| 101 | |
| 102 | **include** - Header files for core and common code. |
| 103 | |
| 104 | **util** - Host utilities and scripts for flashing the EC. Also includes |
| 105 | “ectool” used to query and send commands to the EC from userspace. |
| 106 | |
Tom Hughes | 2f40b71 | 2021-01-26 18:38:55 | [diff] [blame] | 107 | **test** - Unit tests for EC components. These can be run locally in a mock |
| 108 | "host" environment or compiled for a target board. If building for a target |
| 109 | board, the test must be flashed and run manually on the device. All unit tests |
| 110 | and fuzzers are build/run using the local host environment during a `buildall`. |
| 111 | To run all unit tests locally, run `make runhosttests -j`. To build a specific |
| 112 | unit test for a specific board, run `make test-<test_name> BOARD=<board_name>`. |
| 113 | Please contribute new tests if writing new functionality. Please run `make help` |
| 114 | for more detail. |
Craig Hesling | 053491b | 2019-07-02 01:10:37 | [diff] [blame] | 115 | |
Tom Hughes | 2f40b71 | 2021-01-26 18:38:55 | [diff] [blame] | 116 | **fuzz** - Fuzzers for EC components. These fuzzers are expected to run in the |
| 117 | mock host environment. They follow the same rules as unit tests, as thus use the |
| 118 | same commands to build and run. |
Tom Hughes | 80ea7fa | 2019-06-11 21:02:40 | [diff] [blame] | 119 | |
| 120 | ## Firmware Branches |
| 121 | |
| 122 | Each Chrome device has a firmware branch created when the read-only firmware is |
| 123 | locked down prior to launch. This is done so that updates can be made to the |
| 124 | read-write firmware with a minimal set of changes from the read-only. Some |
| 125 | Chrome devices only have build targets on firmware branches and not on |
Dossym Nurmukhanov | 7d9a425 | 2021-02-02 05:45:38 | [diff] [blame] | 126 | cros/main. Run “`git branch -a | grep firmware`” to locate the firmware branch |
Tom Hughes | 80ea7fa | 2019-06-11 21:02:40 | [diff] [blame] | 127 | for your board. Note that for devices still under development, the board |
| 128 | configuration may be on the branch for the platform reference board. |
| 129 | |
| 130 | To build EC firmware on a branch, just check it out and build it: |
| 131 | |
| 132 | ```bash |
| 133 | git checkout cros/firmware-falco_peppy-4389.B |
| 134 | ``` |
| 135 | |
| 136 | To make changes on a branch without creating a whole new development environment |
| 137 | (chroot), create a local tracking branch: |
| 138 | |
| 139 | ```bash |
| 140 | git branch --track firmware-falco_peppy-4389.B cros/firmware-falco_peppy-4389.B |
| 141 | |
| 142 | git checkout firmware-falco_peppy-4389.B |
| 143 | |
| 144 | make clobber |
| 145 | |
| 146 | # <make changes, test, and commit them> |
| 147 | |
| 148 | repo upload --cbr . |
| 149 | |
| 150 | # (The --cbr means "upload to the current branch") |
| 151 | ``` |
| 152 | |
| 153 | Here is a useful command to see commit differences between branches (change the |
| 154 | branch1...branch2 as needed): |
| 155 | |
| 156 | ```bash |
| 157 | git log --left-right --graph --cherry-pick --oneline branch1...branch2 |
| 158 | ``` |
| 159 | |
Tom Hughes | c15e3c7 | 2021-02-02 18:32:14 | [diff] [blame] | 160 | For example, to see the difference between cros/main and the HEAD of the current |
| 161 | branch: |
Tom Hughes | 80ea7fa | 2019-06-11 21:02:40 | [diff] [blame] | 162 | |
| 163 | ```bash |
Dossym Nurmukhanov | 7d9a425 | 2021-02-02 05:45:38 | [diff] [blame] | 164 | git log --left-right --graph --cherry-pick --oneline cros/main...HEAD |
Tom Hughes | 80ea7fa | 2019-06-11 21:02:40 | [diff] [blame] | 165 | |
| 166 | # Note: Use three dots “...” or it won’t work! |
| 167 | ``` |
| 168 | |
| 169 | ## Building an EC binary |
| 170 | |
| 171 | Note: The EC is normally built from within the Chromium OS development chroot to |
| 172 | use the correct toolchain. |
| 173 | |
| 174 | Building directly from the EC repository: |
| 175 | |
| 176 | ```bash |
| 177 | cros_sdk |
Keith Short | 0f52d7a | 2023-01-12 16:01:44 | [diff] [blame] | 178 | cd ~/chromiumos/src/platform/ec |
Tom Hughes | 80ea7fa | 2019-06-11 21:02:40 | [diff] [blame] | 179 | make -j BOARD=<boardname> |
| 180 | ``` |
| 181 | |
Patrick Thompson | a77fc18 | 2022-07-06 18:06:03 | [diff] [blame] | 182 | Where `<boardname>` is replaced by the name of the board you want to build an |
Tom Hughes | 80ea7fa | 2019-06-11 21:02:40 | [diff] [blame] | 183 | EC binary for. For example, the boardname for the Chromebook Pixel is “link”. |
| 184 | The make command will generate an EC binary at `build/<boardname>/ec.bin`. The |
| 185 | `-j` tells make to build multi-threaded which can be much faster on a multi-core |
| 186 | machine. |
| 187 | |
| 188 | ### Building via emerge (the build file used when you build Chrome OS): |
| 189 | |
| 190 | (optional) Run this command if you want to build from local source instead of |
| 191 | the most recent stable version: |
| 192 | |
| 193 | ```bash |
| 194 | cros_workon-<boardname> start chromeos-ec |
| 195 | ``` |
| 196 | |
| 197 | Build the EC binary: |
| 198 | |
| 199 | ``` |
| 200 | emerge-<boardname> chromeos-ec |
| 201 | ``` |
| 202 | |
| 203 | Please be careful if doing both local `make`s and running emerge. The emerge can |
| 204 | pick up build artifacts from the build subdirectory. It’s best to delete the |
| 205 | build directory before running emerge with `make clobber`. |
| 206 | |
| 207 | The generated EC binary from emerge is found at: |
| 208 | |
| 209 | ``` |
| 210 | (chroot) $ /build/<boardname>/firmware/ec.bin |
| 211 | ``` |
| 212 | |
mparuchuri | 1bd5991 | 2022-05-04 08:37:00 | [diff] [blame] | 213 | or |
| 214 | |
| 215 | ``` |
| 216 | (chroot) $ /build/<boardname>/firmware/<devicename>/ec.bin |
| 217 | ``` |
| 218 | |
| 219 | The `devicename` is the name of a device (also referred as board or variant) which belongs to a family of baseboard. `boardname` is the baseboard name in this case. Example : `/build/dedede/firmware/madoo/ec.bin` |
| 220 | |
Tom Hughes | 80ea7fa | 2019-06-11 21:02:40 | [diff] [blame] | 221 | The ebuild file used by Chromium OS is found |
Dossym Nurmukhanov | 7d9a425 | 2021-02-02 05:45:38 | [diff] [blame] | 222 | [here](https://chromium.googlesource.com/chromiumos/overlays/chromiumos-overlay/+/main/chromeos-base/chromeos-ec/chromeos-ec-9999.ebuild): |
Tom Hughes | 80ea7fa | 2019-06-11 21:02:40 | [diff] [blame] | 223 | |
| 224 | ```bash |
| 225 | (chroot) $ ~/trunk/src/third_party/chromiumos-overlay/chromeos-base/chromeos-ec/chromeos-ec-9999.ebuild |
| 226 | ``` |
| 227 | |
| 228 | ## Flashing an EC binary to a board |
| 229 | |
| 230 | ### Flashing via the servo debug board |
| 231 | |
| 232 | If you get an error, you may not have set up the dependencies for servo |
| 233 | correctly. The EC (on current Chromebooks) must be powered either by external |
| 234 | power or a charged battery for re-flashing to succeed. You can re-flash via |
| 235 | servo even if your existing firmware is bad. |
| 236 | |
| 237 | ```bash |
| 238 | (chroot) $ sudo emerge openocd |
| 239 | ``` |
| 240 | |
| 241 | ```bash |
| 242 | (chroot) $ ~/trunk/src/platform/ec/util/flash_ec --board=<boardname> [--image=<path/to/ec.bin>] |
| 243 | ``` |
| 244 | |
| 245 | Note: This command will fail if write protect is enabled. |
| 246 | |
| 247 | If you build your own EC firmware with the `make BOARD=<boardname>` command the |
| 248 | firmware image will be at: |
| 249 | |
| 250 | ```bash |
| 251 | (chroot) $ ~/trunk/src/platform/ec/build/<boardname>/ec.bin |
| 252 | ``` |
| 253 | |
| 254 | If you build Chrome OS with `build_packages` the firmware image will be at: |
| 255 | |
| 256 | ```bash |
| 257 | (chroot) $ /build/<boardname>/firmware/ec.bin |
| 258 | ``` |
| 259 | |
mparuchuri | 1bd5991 | 2022-05-04 08:37:00 | [diff] [blame] | 260 | or |
| 261 | |
| 262 | ``` |
| 263 | (chroot) $ /build/<boardname>/firmware/<devicename>/ec.bin |
| 264 | ``` |
| 265 | |
| 266 | The `devicename` is the name of a device (also referred as board or variant) which belongs to a family of baseboard. `boardname` is the baseboard name in this case. Example : `/build/dedede/firmware/madoo/ec.bin` |
| 267 | |
Tom Hughes | 80ea7fa | 2019-06-11 21:02:40 | [diff] [blame] | 268 | Specifying `--image` is optional. If you leave off the `--image` argument, the |
| 269 | `flash_ec` script will first look for a locally built `ec.bin` followed by one |
| 270 | generated by `emerge`. |
| 271 | |
| 272 | ### Flashing on-device via flashrom |
| 273 | |
| 274 | Assuming your devices boots, you can flash it using the `flashrom` utility. Copy |
| 275 | your binary to the device and run: |
| 276 | |
| 277 | ```bash |
| 278 | (chroot) $ flashrom -p ec -w <path-to/ec.bin> |
| 279 | ``` |
| 280 | |
| 281 | Note: `-p internal:bus=lpc` also works on x86 boards...but why would you want to |
| 282 | remember and type all that? |
| 283 | |
| 284 | ## Preventing the RW EC firmware from being overwritten by Software Sync at boot |
| 285 | |
| 286 | A feature called "Software Sync" keeps a copy of the read-write (RW) EC firmware |
| 287 | in the RW part of the system firmware image. At boot, if the RW EC firmware |
| 288 | doesn't match the copy in the system firmware, the EC’s RW section is |
| 289 | re-flashed. While this is great for normal use as it makes updating the EC and |
| 290 | system firmware a unified operation, it can be a challenge for EC firmware |
| 291 | development. To disable software sync a flag can be set in the system firmware. |
| 292 | Run the following commands from a shell on the device to disable Software Sync |
| 293 | and turn on other developer-friendly flags (note that write protect must be |
| 294 | disabled for this to work): |
| 295 | |
| 296 | ```bash |
Edward O'Callaghan | 611a9ab | 2023-01-12 22:25:05 | [diff] [blame] | 297 | # futility gbb --set --flash --flags=0x239 |
Tom Hughes | 80ea7fa | 2019-06-11 21:02:40 | [diff] [blame] | 298 | ``` |
| 299 | |
| 300 | ```bash |
Fabio Baltieri | bcbd953 | 2021-01-21 22:19:35 | [diff] [blame] | 301 | # reboot |
Tom Hughes | 80ea7fa | 2019-06-11 21:02:40 | [diff] [blame] | 302 | ``` |
| 303 | |
| 304 | This turns on the following flags: |
| 305 | |
| 306 | * `GBB_FLAG_DEV_SCREEN_SHORT_DELAY` |
| 307 | * `GBB_FLAG_FORCE_DEV_SWITCH_ON` |
| 308 | * `GBB_FLAG_FORCE_DEV_BOOT_USB` |
| 309 | * `GBB_FLAG_DISABLE_FW_ROLLBACK_CHECK` |
| 310 | * `GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC` |
| 311 | |
Fabio Baltieri | e925422 | 2023-06-08 09:09:57 | [diff] [blame] | 312 | |
| 313 | Alternatively, if the OS cannot be accessed, the same flag can be set over a servo with: |
| 314 | |
| 315 | ```bash |
| 316 | $ sudo futility gbb -s --flags=0x239 --servo |
| 317 | ``` |
| 318 | |
Tom Hughes | 80ea7fa | 2019-06-11 21:02:40 | [diff] [blame] | 319 | The `GBB` (Google Binary Block) flags are defined in the |
Dossym Nurmukhanov | 7d9a425 | 2021-02-02 05:45:38 | [diff] [blame] | 320 | [vboot_reference source](https://chromium.googlesource.com/chromiumos/platform/vboot_reference/+/main/firmware/2lib/include/2struct.h). |
Tom Hughes | 80ea7fa | 2019-06-11 21:02:40 | [diff] [blame] | 321 | A varying subset of these flags are implemented and/or relevant for any |
| 322 | particular board. |
| 323 | |
| 324 | ## Using the EC serial console |
| 325 | |
| 326 | The EC has an interactive serial console available only through the UART |
| 327 | connected via servo. This console is essential to developing and debugging the |
| 328 | EC. |
| 329 | |
| 330 | Find the serial device of the ec console (on your workstation): |
| 331 | |
| 332 | ```bash |
Mary Ruthven | 076dd70 | 2019-09-20 18:10:15 | [diff] [blame] | 333 | (chroot) $ dut-control ec_uart_pty |
Tom Hughes | 80ea7fa | 2019-06-11 21:02:40 | [diff] [blame] | 334 | ``` |
| 335 | |
| 336 | Connect to the console: |
| 337 | |
| 338 | ```bash |
| 339 | (chroot) $ socat READLINE /dev/pts/XX |
| 340 | ``` |
| 341 | |
| 342 | Where `XX` is the device number. Use `cu`, `minicom`, or `screen` if you prefer |
| 343 | them over `socat`. |
| 344 | |
| 345 | ### Useful EC console commands: |
| 346 | |
| 347 | **help** - get a list of commands. help <command> to get help on a specific |
| 348 | command. |
| 349 | |
| 350 | **chan** - limit logging message to specific tasks (channels). Useful if you’re |
| 351 | looking for a specific error or warning and don’t want spam from other tasks. |
| 352 | |
| 353 | **battfake** - Override the reported battery charge percentage. Good for testing |
| 354 | low battery conditions (LED behavior for example). Set “battfake -1” to go back |
| 355 | to the actual value. |
| 356 | |
| 357 | **fanduty** - Override automatic fan control. “fanduty 0” turns the fan off. |
| 358 | “autofan” switches back to automated control. |
| 359 | |
| 360 | **hcdebug** - Display the commands that the host sends to the EC, in varying |
| 361 | levels of detail (see include/ec_commands.h for the data structures). |
| 362 | |
| 363 | ## Host commands |
| 364 | |
| 365 | The way in which messages are exchanged between the AP and EC is |
Harry Cutts | 14b13d3 | 2019-11-06 01:14:44 | [diff] [blame] | 366 | [documented separately](./docs/ap-ec-comm.md). |
Tom Hughes | 80ea7fa | 2019-06-11 21:02:40 | [diff] [blame] | 367 | |
| 368 | ## Software Features |
| 369 | |
| 370 | ### Tasks |
| 371 | |
| 372 | Most code run on the EC after initialization is run in the context of a task |
| 373 | (with the rest in interrupt handlers). Each task has a fixed stack size and |
| 374 | there is no heap (malloc). All variable storage must be explicitly declared at |
| 375 | build-time. The EC (and system) will reboot if any task has a stack overflow. |
| 376 | Tasks typically have a top-level loop with a call to task_wait_event() or |
Patryk Duda | 85d7598 | 2024-04-10 13:10:59 | [diff] [blame] | 377 | crec_usleep() to set a delay in uSec before continuing. A watchdog will trigger |
| 378 | if a task runs for too long. The watchdog timeout varies by EC chip and the |
| 379 | clock speed the EC is running at. |
Tom Hughes | 80ea7fa | 2019-06-11 21:02:40 | [diff] [blame] | 380 | |
| 381 | The list of tasks for a board is specified in ec.tasklist in the `board/$BOARD/` |
| 382 | sub-directory. Tasks are listed in priority order with the lowest priority task |
| 383 | listed first. A task runs until it exits its main function or puts itself to |
| 384 | sleep. The highest priority task that wants to run is scheduled next. Tasks can |
| 385 | be preempted at any time by an interrupt and resumed after the handler is |
| 386 | finished. |
| 387 | |
| 388 | The console `taskinfo` command will print run-time stats on each task: |
| 389 | |
| 390 | ``` |
| 391 | > taskinfo |
| 392 | Task Ready Name Events Time (s) StkUsed |
| 393 | 0 R << idle >> 00000000 32.975554 196/256 |
| 394 | 1 R HOOKS 00000000 0.007835 192/488 |
| 395 | 2 VBOOTHASH 00000000 0.042818 392/488 |
| 396 | 3 POWERLED 00000000 0.000096 120/256 |
| 397 | 4 CHARGER 00000000 0.029050 392/488 |
| 398 | 5 CHIPSET 00000000 0.017558 400/488 |
| 399 | 6 HOSTCMD 00000000 0.379277 328/488 |
| 400 | 7 R CONSOLE 00000000 0.042050 348/640 |
| 401 | 8 KEYSCAN 00000000 0.002988 292/488 |
| 402 | ``` |
| 403 | |
| 404 | The `StkUsed` column reports the largest size the stack for each task grew since |
| 405 | reset (or sysjump). |
| 406 | |
| 407 | ### Hooks |
| 408 | |
| 409 | Hooks allow you to register a function to be run when specific events occur; |
| 410 | such as the host suspending or external power being applied: |
| 411 | |
| 412 | ``` |
| 413 | DECLARE_HOOK(HOOK_AC_CHANGE, ac_change_callback, HOOK_PRIO_DEFAULT); |
| 414 | ``` |
| 415 | |
| 416 | Registered functions are run in the HOOKS task. Registered functions are called |
| 417 | in priority order if more than one callback needs to be run. There are also |
| 418 | hooks for running functions periodically: `HOOK_TICK` (fires every |
| 419 | `HOOK_TICK_INVERVAL` ms which varies by EC chip) and `HOOK_SECOND`. See |
| 420 | hook_type in |
Dossym Nurmukhanov | 7d9a425 | 2021-02-02 05:45:38 | [diff] [blame] | 421 | [include/hooks.h](https://chromium.googlesource.com/chromiumos/platform/ec/+/main/include/hooks.h) |
Tom Hughes | 80ea7fa | 2019-06-11 21:02:40 | [diff] [blame] | 422 | for a complete list. |
| 423 | |
| 424 | ### Deferred Functions |
| 425 | |
| 426 | Deferred functions allow you to call a function after a delay specified in uSec |
| 427 | without blocking. Deferred functions run in the HOOKS task. Here is an example |
| 428 | of an interrupt handler. The deferred function allows the handler itself to be |
| 429 | lightweight. Delaying the deferred call by 30 mSec also allows the interrupt to |
| 430 | be debounced. |
| 431 | |
| 432 | ``` |
| 433 | static int debounced_gpio_state; |
| 434 | |
| 435 | static void some_interrupt_deferred(void) |
| 436 | { |
| 437 | |
| 438 | int gpio_state = gpio_get_level(GPIO_SOME_SIGNAL); |
| 439 | |
| 440 | if (gpio_state == debounced_gpio_state) |
| 441 | return; |
| 442 | |
| 443 | debounced_gpio_state = gpio_state; |
| 444 | |
| 445 | dispense_sandwich(); /* Or some other useful action. */ |
| 446 | } |
| 447 | |
| 448 | /* A function must be explicitly declared as being deferrable. */ |
| 449 | DECLARE_DEFERRED(some_interrupt_deferred); |
| 450 | |
| 451 | void some_interrupt(enum gpio_signal signal) |
| 452 | { |
| 453 | hook_call_deferred(some_interrupt_deferred, 30 * MSEC); |
| 454 | } |
| 455 | ``` |
| 456 | |
| 457 | ### Shared Memory Buffer |
| 458 | |
| 459 | While there is no heap, there is a shared memory buffer that can be borrowed |
| 460 | temporarily (ideally before a context switch). The size of the buffer depends on |
| 461 | the EC chip being used. The buffer can only be used by one task at a time. See |
Dossym Nurmukhanov | 7d9a425 | 2021-02-02 05:45:38 | [diff] [blame] | 462 | [common/shared_mem.c](https://chromium.googlesource.com/chromiumos/platform/ec/+/main/common/shared_mem.c) |
Tom Hughes | 80ea7fa | 2019-06-11 21:02:40 | [diff] [blame] | 463 | for more information. At present (May 2014), this buffer is only used by debug |
| 464 | commands. |
| 465 | |
| 466 | ## Making Code Changes |
| 467 | |
| 468 | If you see a bug or want to make an improvement to the EC code please file an |
| 469 | issue at [crbug.com/new](http://crbug.com/new). It's best to discuss the change |
| 470 | you want to make first on an issue report to make sure the EC maintainers are |
| 471 | on-board before digging into the fun part (writing code). |
| 472 | |
| 473 | In general, make more, smaller changes that solve single problems rather than |
| 474 | bigger changes that solve multiple problems. Smaller changes are easier and |
| 475 | faster to review. When changing common code shared between boards along with |
| 476 | board specific code, please split the shared code change into its own change |
| 477 | list (CL). The board specific CL can depend on the shared code CL. |
| 478 | |
| 479 | ### Coding style |
| 480 | |
| 481 | The EC code follows the |
| 482 | [Linux Kernel style guide](https://www.kernel.org/doc/html/latest/process/coding-style.html). |
| 483 | Please adopt the same style used in the existing code. Use tabs, not spaces, 80 |
| 484 | column lines etc... |
| 485 | |
| 486 | Other style notes: |
| 487 | |
| 488 | 1. Globals should either be `static` or `const`. Use them for persistent state |
| 489 | within a file or for constant data (such as the GPIO list in board.c). Do |
| 490 | not use globals to pass information between modules without accessors. For |
| 491 | module scope, accessors are not needed. |
| 492 | 1. If you add a new `#define` config option to the code, please document it in |
Dossym Nurmukhanov | 7d9a425 | 2021-02-02 05:45:38 | [diff] [blame] | 493 | [include/config.h](https://chromium.googlesource.com/chromiumos/platform/ec/+/main/include/config.h) |
Tom Hughes | 80ea7fa | 2019-06-11 21:02:40 | [diff] [blame] | 494 | with an `#undef` statement and descriptive comment. |
| 495 | 1. The Chromium copyright header must be included at the top of new files in |
| 496 | all contributions to the Chromium project: |
| 497 | |
| 498 | ``` |
Mike Frysinger | 71b2ef7 | 2022-09-12 18:54:36 | [diff] [blame] | 499 | /* Copyright <year> The ChromiumOS Authors |
Tom Hughes | 80ea7fa | 2019-06-11 21:02:40 | [diff] [blame] | 500 | * Use of this source code is governed by a BSD-style license that can be |
| 501 | * found in the LICENSE file. |
| 502 | */ |
| 503 | ``` |
| 504 | |
| 505 | ### Submitting changes |
| 506 | |
| 507 | Prior to uploading a new change for review, please run the EC unit tests with: |
| 508 | |
| 509 | ```bash |
| 510 | (chroot) $ make -j buildall |
| 511 | ``` |
| 512 | |
| 513 | ```bash |
Ting Shen | c32a659 | 2023-09-13 07:52:28 | [diff] [blame] | 514 | (chroot) $ make -j runtests |
Tom Hughes | 80ea7fa | 2019-06-11 21:02:40 | [diff] [blame] | 515 | ``` |
| 516 | |
Ting Shen | c32a659 | 2023-09-13 07:52:28 | [diff] [blame] | 517 | These commands will build and run unit tests on your host. |
Tom Hughes | 80ea7fa | 2019-06-11 21:02:40 | [diff] [blame] | 518 | |
Jack Rosenthal | 6db4ddb | 2023-05-02 01:23:42 | [diff] [blame] | 519 | Pre-upload checks are run when you try to upload a change-list. If you wish to |
Tom Hughes | 80ea7fa | 2019-06-11 21:02:40 | [diff] [blame] | 520 | run these checks manually first, commit your change locally then run the |
| 521 | following command from within the chroot and while in the `src/platform/ec` |
| 522 | directory: |
| 523 | |
| 524 | ```bash |
| 525 | (chroot) $ ~/trunk/src/repohooks/pre-upload.py |
| 526 | ``` |
| 527 | |
Jack Rosenthal | 6db4ddb | 2023-05-02 01:23:42 | [diff] [blame] | 528 | The pre-upload checks include checking the commit message. Commit messages must |
| 529 | have a `BUG` and `TEST`. You may also optionally include a `BRANCH` line with a |
| 530 | list of board names for which the CL should be cherry-picked back to old |
| 531 | branches for. |
Tom Hughes | 80ea7fa | 2019-06-11 21:02:40 | [diff] [blame] | 532 | |
| 533 | Please refer to existing commits (`git log`) to see the proper format for the |
Jack Rosenthal | 6db4ddb | 2023-05-02 01:23:42 | [diff] [blame] | 534 | commit message. |
Tom Hughes | 80ea7fa | 2019-06-11 21:02:40 | [diff] [blame] | 535 | |
Keith Short | 0f52d7a | 2023-01-12 16:01:44 | [diff] [blame] | 536 | Note that code you submit must adhere to the [ChromeOS EC Firmware Test |
| 537 | Requirements]. |
| 538 | |
Tom Hughes | 80ea7fa | 2019-06-11 21:02:40 | [diff] [blame] | 539 | ## Debugging |
| 540 | |
| 541 | While adding `printf` statements can be handy, there are some other options for |
| 542 | debugging problems during development. |
| 543 | |
| 544 | ### Serial Console |
| 545 | |
| 546 | There may already be a message on the serial console that indicates your |
| 547 | problem. If you don’t have a servo connected, the `ectool console` command will |
| 548 | show the current contents of the console buffer (the buffer’s size varies by EC |
| 549 | chip). This log persists across warm resets of the host but is cleared if the EC |
| 550 | resets. The `ectool console` command will only work when the EC is not write |
| 551 | protected. |
| 552 | |
| 553 | If you have interactive access to the serial console via servo, you can use the |
| 554 | read word `rw` and write word `ww` commands to peek and poke the EC's RAM. You |
| 555 | may need to refer to the datasheet for your EC chip or the disassembled code to |
| 556 | find the memory address you need. There are other handy commands on the serial |
| 557 | console to read temperatures, view the state of tasks (taskinfo) which may help. |
| 558 | Type `help` for a list. |
| 559 | |
| 560 | ### Panicinfo |
| 561 | |
| 562 | The EC may save panic data which persists across resets. Use the “`ectool |
| 563 | panicinfo`” command or console “`panicinfo`” command to view the saved data: |
| 564 | |
| 565 | ``` |
| 566 | Saved panic data: (NEW) |
| 567 | === HANDLER EXCEPTION: 05 ====== xPSR: 6100001e === |
| 568 | r0 :00000001 r1 :00000f15 r2 :4003800c r3 :000000ff |
| 569 | r4 :ffffffed r5 :00000799 r6 :0000f370 r7 :00000000 |
| 570 | r8 :00000001 r9 :00000003 r10:20002fe0 r11:00000000 |
| 571 | r12:00000008 sp :20000fd8 lr :000012e1 pc :0000105e |
| 572 | ``` |
| 573 | |
| 574 | The most interesting information are the program counter (`pc`) and the link |
| 575 | register (return address, `lr`) as they give you an indication of what code the |
| 576 | EC was running when the panic occurred. `HANDLER EXCEPTIONS` indicate the panic |
| 577 | occurred while servicing an interrupt. `PROCESS EXCEPTIONS` occur in regular |
| 578 | tasks. If you see “Imprecise data bus error” listed, the program counter value |
| 579 | is incorrect as the panic occurred when flushing a write buffer. If using a |
| 580 | cortex-m based EC, add `CONFIG_DEBUG_DISABLE_WRITE_BUFFER` to your board.h to |
| 581 | disable write buffering (with a performance hit) to get a “Precise bus error” |
| 582 | with an accurate program counter value. |
| 583 | |
| 584 | ### Assembly Code |
| 585 | |
| 586 | If you have a program counter address you need to make sense of, you can |
| 587 | generate the assembly code for the EC by checking out the code at the matching |
| 588 | commit for your binary (`ectool version`) and running: |
| 589 | |
| 590 | ```bash |
| 591 | (chroot) $ make BOARD=$board dis |
| 592 | ``` |
| 593 | |
| 594 | This outputs two files with assembly code: |
| 595 | |
| 596 | ``` |
| 597 | build/$board/RO/ec.RO.dis |
| 598 | build/$board/RW/ec.RW.dis |
| 599 | ``` |
| 600 | |
| 601 | which (in the case of the LM4 and STM32) are essentially the same, but the RW |
| 602 | addresses are offset. |
| 603 | |
| 604 | ## Write Protect |
| 605 | |
Tom Hughes | 6f76b0a | 2019-06-13 18:24:19 | [diff] [blame] | 606 | See [Firmware Write Protection]. |
Tom Hughes | 80ea7fa | 2019-06-11 21:02:40 | [diff] [blame] | 607 | |
| 608 | ## EC Version Strings |
| 609 | |
| 610 | The read-only and read-write sections of the EC firmware each have a version |
| 611 | string. This string tells you the branch and last change at which the firmware |
| 612 | was built. On a running machine, run `ectool version` from a shell to see |
| 613 | version information: |
| 614 | |
| 615 | ``` |
| 616 | RO version: peppy_v1.5.103-7abb4f7 |
| 617 | RW version: peppy_v1.5.129-cd1a1e9 |
| 618 | Firmware copy: RW |
| 619 | Build info: peppy_v1.5.129-cd1a1e9 2014-03-07 17:18:27 @build120-m2 |
| 620 | ``` |
| 621 | |
| 622 | You can also run the `version` command on the EC serial console for a similar |
| 623 | output. |
| 624 | |
| 625 | The format of the version string is: |
| 626 | |
| 627 | ``` |
| 628 | <board>_<branch number>.<number of commits since the branch tag was created>-<git hash of most recent change> |
| 629 | ``` |
| 630 | |
| 631 | If the version is: `rambi_v1.6.68-a6608c8`: |
| 632 | |
| 633 | * board name = rambi |
| 634 | * branch number = v1.6 (which is for the firmware-rambi branch) |
| 635 | * number of commits on this branch (since the tag was added) = 68 |
| 636 | * latest git hash = a6608c8 |
| 637 | |
| 638 | The branch numbers (as of May 2014) are: |
| 639 | |
Dossym Nurmukhanov | 7d9a425 | 2021-02-02 05:45:38 | [diff] [blame] | 640 | * v1.0.0 cros/main |
| 641 | * v1.1.0 cros/main |
Tom Hughes | 80ea7fa | 2019-06-11 21:02:40 | [diff] [blame] | 642 | * v1.2.0 cros/firmware-link-2695.2.B |
| 643 | * v1.3.0 cros/firmware-snow-2695.90.B |
| 644 | * v1.4.0 cros/firmware-skate-3824.129.B |
| 645 | * v1.5.0 cros/firmware-4389.71.B |
| 646 | * v1.6.0 cros/firmware-rambi-5216.B |
| 647 | |
| 648 | Hack command to check the branch tags: |
| 649 | |
| 650 | ``` |
| 651 | git tag |
| 652 | |
| 653 | for hash in $(git for-each-ref --format='%(objectname)' refs/tags/); do |
| 654 | git branch -a --contains $hash | head -1; |
| 655 | done |
| 656 | ``` |
| 657 | |
| 658 | (If anyone can come up with something prettier, make a CL). |
| 659 | |
| 660 | Run `util/getversion.sh` to see the current version string. The board name is |
| 661 | passed as an environment variable `BOARD`: |
| 662 | |
| 663 | ```bash |
| 664 | (chroot) $ BOARD="cheese" ./util/getversion.sh |
| 665 | ``` |
| 666 | |
| 667 | ``` |
| 668 | cheese_v1.1.1755-4da9520 |
| 669 | ``` |
Tom Hughes | 6f76b0a | 2019-06-13 18:24:19 | [diff] [blame] | 670 | |
| 671 | [Firmware Write Protection]: ./docs/write_protection.md |
Jeremy Bettis | b3b3836 | 2022-03-16 16:20:26 | [diff] [blame] | 672 | |
| 673 | ## CQ builder |
| 674 | |
| 675 | To test the cq builder script run these commands: |
| 676 | |
| 677 | ### firmware-ec-cq |
| 678 | ``` |
| 679 | rm -rf /tmp/artifact_bundles /tmp/artifact_bundle_metadata \ |
| 680 | ~/chromiumos/src/platform/ec/build |
| 681 | ./firmware_builder.py --metrics /tmp/metrics_build build && \ |
| 682 | ./firmware_builder.py --metrics /tmp/metrics_test test && \ |
| 683 | ./firmware_builder.py --metrics /tmp/metrics_bundle bundle && \ |
| 684 | echo PASSED |
| 685 | cat /tmp/artifact_bundle_metadata |
| 686 | cat /tmp/metrics_build |
| 687 | ls -l /tmp/artifact_bundles/ |
| 688 | ``` |
Keith Short | 0f52d7a | 2023-01-12 16:01:44 | [diff] [blame] | 689 | |
| 690 | [ChromeOS EC Firmware Test Requirements]: ./docs/chromeos-ec-firmware-test-requirements.md |