|
| 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. |
0 commit comments