Skip to content

Commit e742da8

Browse files
authored
docs: Add new board guide (zmkfirmware#3181)
* docs: Add new board guide * docs: apply feedback from review
1 parent ada1542 commit e742da8

3 files changed

Lines changed: 189 additions & 1 deletion

File tree

docs/docs/development/hardware-integration/index.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ And other miscellaneous ones:
111111
- A `<keyboard_name>.zmk.yml` file containing [metadata](hardware-metadata-files.md) for the keyboard.
112112

113113
See Zephyr's [board porting guide](https://docs.zephyrproject.org/4.1.0/hardware/porting/board_porting.html) for information on creating a new board.
114-
Also see the [new keyboard shield guide](new-shield.mdx#shield-overlays) for information on parts of the devicetree specifically related to ZMK.
114+
See also our [new board guide](new-board.md) for information on creating a ZMK-compatible board variant.
115115

116116
[^1]:
117117
Parts of these files can live in separate `.dtsi` files (typically in the same directory) that are then `#include`d in the files, to reduce duplication or improve organization.
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
---
2+
title: New Board
3+
---
4+
5+
This guide will walk through the necessary steps to write a [board](./index.mdx#boards--shields) suitable for use with ZMK. Boards used with ZMK fall into two categories:
6+
7+
- Boards with interconnects, such as `nice_nano` or `seeed_xiao`. Such boards will (active development of ZMK aside) always be used with a shield to create a keyboard.
8+
- Boards that are themselves keyboards, such as `bt75` or `ferris`.
9+
10+
Some keyboards are boards but also have interconnects for modular add-ons. These are considered as keyboard-boards for the purpose of this guide. Details on adding an interconnect for modular add-ons are considered out of scope.
11+
12+
## Boards Included in ZMK
13+
14+
Boards with interconnects can be considered for inclusion to the tree of ZMK. If this is your aim, it is vital that you read through our [clean room policy](../contributing/clean-room.md).
15+
16+
Boards with interconnects that are included with ZMK are generally:
17+
18+
- Reliably commercially available as individual units
19+
- In regular use across multiple shields (i.e. not niche)
20+
21+
Popular open source designs which are not being sold can also be considered for inclusion.
22+
23+
There also exist many boards in the tree of upstream Zephyr. We generally accept ZMK-variants of these boards into our tree as well.
24+
25+
## New ZMK Module Repository
26+
27+
Regardless of whether you aim to include the board in ZMK or not, you should first write the definition for it in a module. A new ZMK module repository can be created from a template.
28+
29+
:::note
30+
This guide assumes you already have a configured GitHub account. If you don't yet have one, go ahead and [sign up](https://github.com/join) before continuing.
31+
:::
32+
33+
Follow these steps to create your new repository:
34+
35+
- Visit https://github.com/zmkfirmware/unified-zmk-config-template
36+
- Click the green "Use this template" button
37+
- In the drop down that opens, click "Use this template".
38+
- In the following screen, provide the following information:
39+
- A repository name, e.g. `my-board-module`.
40+
- A brief description, e.g. `ZMK Support For MyBoard`.
41+
- Select Public or Private, depending on your preference.
42+
- Click the green "Create repository" button
43+
44+
The repository is a combination of the directories and files required of a ZMK config, and those required of a shield module.
45+
This enables the use of GitHub Actions to test that the shield is defined correctly.
46+
See also the page on [module creation](../module-creation.md) for a reference on exactly which file structure and files are required for a ZMK keyboard module.
47+
48+
We recommend that you take this moment to name your module according to our [convention](../module-creation.md), i.e. your `zephyr/module.yml` file should begin with
49+
50+
```yaml title="zephyr/module.yml"
51+
name: zmk-keyboard-<keyboard_name>
52+
```
53+
54+
if it is a keyboard, or
55+
56+
```yaml title="zephyr/module.yml"
57+
name: zmk-component-<board_name>
58+
```
59+
60+
if it is a board with an interconnect.
61+
62+
## Write a Zephyr Board Definition
63+
64+
Zephyr has a guide on writing a board [here](https://docs.zephyrproject.org/4.1.0/hardware/porting/board_porting.html). Follow this guide to create a Zephyr-compatible board. Use the `boards` folder of your ZMK module as a base.
65+
66+
Once your board definition has been written, we recommend flashing some [Zephyr samples](https://docs.zephyrproject.org/4.1.0/samples/basic/basic.html) to it, to verify that it is working.
67+
68+
Flashing Zephyr samples can also be very helpful when troubleshooting/testing the functionality of extra features such as LED ICs, Bluetooth, or various sensor ICs.
69+
70+
## Write a ZMK Variant of Zephyr Board
71+
72+
To make a board fully compatible with ZMK, you will be creating a ZMK variant of the Zephyr board you made in the previous step. Perform the below actions for each board you've defined, in the case of multi-board split keyboards.
73+
74+
### Add Variant to board.yml
75+
76+
Edit your existing `board.yml` file to add the variant:
77+
78+
```yaml title="board.yml"
79+
board:
80+
...
81+
socs:
82+
- name: <soc-1>
83+
variants:
84+
- name: zmk
85+
```
86+
87+
### Add Kconfig for ZMK Variant
88+
89+
Add a file to your board's folder called `<your-board>_zmk_defconfig`. This file will be used to set Kconfig flags specific to the ZMK variant.
90+
91+
:::warning
92+
Make sure you know what each Kconfig flag does before you enable it. Some flags may be incompatible with certain hardware, or have other adverse effects.
93+
:::
94+
95+
These flags are typically a subset of the following:
96+
97+
```yaml title="<your-board>_zmk_defconfig"
98+
# SPDX-License-Identifier: <your license>
99+
100+
# Enable MPU
101+
CONFIG_ARM_MPU=y
102+
103+
CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=125000000
104+
105+
# Enable reset by default
106+
CONFIG_RESET=y
107+
108+
# Enable clock control by default
109+
CONFIG_CLOCK_CONTROL=y
110+
111+
# Code partition needed to target the correct flash range
112+
CONFIG_USE_DT_CODE_PARTITION=y
113+
114+
# Output UF2 by default, native bootloader supports it.
115+
CONFIG_BUILD_OUTPUT_UF2=y
116+
117+
# USB HID
118+
CONFIG_ZMK_USB=y
119+
120+
# BLE HID
121+
CONFIG_ZMK_BLE=y
122+
123+
# Bootloader Support
124+
CONFIG_RETAINED_MEM=y
125+
CONFIG_RETENTION=y
126+
CONFIG_RETENTION_BOOT_MODE=y
127+
128+
# Settings Support
129+
CONFIG_MPU_ALLOW_FLASH_WRITE=y
130+
CONFIG_NVS=y
131+
CONFIG_SETTINGS_NVS=y
132+
CONFIG_FLASH=y
133+
CONFIG_FLASH_PAGE_LAYOUT=y
134+
CONFIG_FLASH_MAP=y
135+
136+
137+
# Enable HW stack protection
138+
CONFIG_HW_STACK_PROTECTION=y
139+
140+
# Enable GPIO
141+
CONFIG_GPIO=y
142+
143+
# Defaults for matrix scanning to avoid interrupt issues
144+
CONFIG_ZMK_KSCAN_MATRIX_POLLING=y
145+
```
146+
147+
Note that none of our in-tree boards have all of the above flags set. We recommend referencing the Kconfig flags from an existing in-tree board with the same SoC as the one you are using for your initial definition, making sure you understand what each flag does.
148+
149+
### Add Devicetree for ZMK Variant
150+
151+
```dts title="<your-board>_zmk.dts
152+
/*
153+
* Copyright (c) <year> <you>
154+
*
155+
* SPDX-License-Identifier: <your license>
156+
*/
157+
158+
// Include the base board definition
159+
#include <../boards/<vendor or you>/<board folder name>/<your board>.dts>
160+
// Include predefined boot mode settings, e.g.
161+
#include <arm/raspberrypi/rp2040-boot-mode-retention.dtsi>
162+
163+
// Disable UART nodes if they are not actively in use (wired split) as they increase power draw
164+
&uart0 { status = "disabled"; };
165+
166+
// Reduce the code partition section of the memory and add a storage partition to store ZMK Studio changes
167+
&code_partition {
168+
reg = <0x100 (DT_SIZE_M(2) - 0x100 - DT_SIZE_K(512))>;
169+
};
170+
&flash0 {
171+
reg = <0x10000000 DT_SIZE_M(2)>;
172+
partitions {
173+
storage_partition: partition@180000 {
174+
reg = <0x180000 DT_SIZE_K(512)>;
175+
read-only;
176+
};
177+
};
178+
};
179+
```
180+
181+
See [here](./bootloader/index.mdx) for bootloader instructions for other SoCs. Depending on your SoC and design you may need to make further changes. Please refer to our in-tree boards with the same SoC as yours as examples.
182+
183+
## Next Steps
184+
185+
If your board is a keyboard, continue from [the `Kconfig.defconfig` step](https://zmk.dev/docs/development/hardware-integration/new-shield?keyboard-type=unibody#kconfigdefconfig) of the new shield guide. Use your ZMK variant's devicetree instead of the overlay file which would be used for a shield.
186+
187+
If your board is a board with an interconnect, your next step should be to write a [tester shield](../../troubleshooting/hardware-issues.mdx#identifying-issues). Such a shield should be the bare minimum shield to verify that your board works with ZMK.

docs/sidebars.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ module.exports = {
158158
"development/hardware-integration/encoders",
159159
"development/hardware-integration/soft-off-setup",
160160
"development/hardware-integration/pointing",
161+
"development/hardware-integration/new-board",
161162
"development/hardware-integration/battery",
162163
{
163164
type: "category",

0 commit comments

Comments
 (0)