Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion app/src/boot/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

target_sources_ifdef(CONFIG_ZMK_BOOTMODE_TO_MAGIC_VALUE_MAPPER app PRIVATE bootmode_to_magic_mapper.c)
target_sources_ifdef(CONFIG_ZMK_DBL_TAP_BOOTLOADER app PRIVATE dbl_tap_bootloader.c)
target_sources_ifdef(CONFIG_ZMK_DBL_TAP_BOOTLOADER app PRIVATE dbl_tap_bootloader.c)
target_sources_ifdef(CONFIG_ZMK_BOOT_STM32_ENFORCE_NBOOT_SEL app PRIVATE stm32_enforce_nboot_sel.c)
8 changes: 8 additions & 0 deletions app/src/boot/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,11 @@ config ZMK_BOOTMODE_BOOTLOADER_MAGIC_VALUE
hex

endif

config ZMK_BOOT_STM32_ENFORCE_NBOOT_SEL
bool
default y
depends on FLASH && (SOC_STM32C071XX || SOC_STM32G0B1XX)
select FLASH_EX_OP_ENABLED
select FLASH_STM32_OPTION_BYTES

1 change: 1 addition & 0 deletions app/src/boot/Kconfig.defaults
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ config ZMK_BOOTMODE_BOOTLOADER_MAGIC_VALUE
default 0x57 if ZMK_BOOTMODE_MAGIC_VALUE_BOOTLOADER_TYPE_ADAFRUIT_NRF52

endif

46 changes: 46 additions & 0 deletions app/src/boot/stm32_enforce_nboot_sel.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#include <soc.h>
#include <zephyr/kernel.h>
#include <zephyr/init.h>
#include <zephyr/drivers/flash.h>
#include <zephyr/drivers/flash/stm32_flash_api_extensions.h>
#include <zephyr/storage/flash_map.h>

#include <zephyr/logging/log.h>

LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);

const struct device *flash_dev = FIXED_PARTITION_DEVICE(storage_partition);

static int stm32_enforce_nboot_sel_init(void) {
uint32_t opts = 0;
int ret = 0;

if (!device_is_ready(flash_dev)) {
LOG_ERR("flash dev not ready");
return 0;
}

ret = flash_ex_op(flash_dev, FLASH_STM32_EX_OP_OPTB_READ, (uintptr_t)NULL, &opts);

if (ret < 0) {
LOG_ERR("Failed to read option bytes with flash ext op (%d)\n", ret);
return ret;
}

LOG_DBG("Current option bytes: %02X\n", opts);

if (opts & FLASH_OPTR_nBOOT_SEL) {
WRITE_BIT(opts, FLASH_OPTR_nBOOT_SEL_Pos, false);

LOG_DBG("Writing new option bytes %02X\n", opts);
ret = flash_ex_op(flash_dev, FLASH_STM32_EX_OP_OPTB_WRITE, opts, NULL);
if (ret < 0) {
LOG_ERR("Failed to write new option bytes (%d)", ret);
return ret;
}
}

return 0;
}

SYS_INIT(stm32_enforce_nboot_sel_init, APPLICATION, 10);
6 changes: 6 additions & 0 deletions app/west.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ manifest:
- openthread
- edtt
- trusted-firmware-m
- name: hal_stm32
revision: 4fcc3a3f32abe1c4cb76d9d1cef967728dd03908
path: modules/hal/stm32
remote: zmkfirmware
groups:
- hal
- name: lvgl
revision: f1db87ee98f1810328a8419572fa42a3b5f352ae
path: modules/lib/gui/lvgl
Expand Down
42 changes: 42 additions & 0 deletions docs/docs/config/bootloader.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
title: Bootloader Integration Configuration
sidebar_label: Bootloader Integration
---

These are general settings that control the various bootloader integration features of ZMK.

See [Configuration Overview](index.md) for instructions on how to change these settings.

## Kconfig

Definition file: [zmk/app/src/boot/Kconfig](https://github.com/zmkfirmware/zmk/blob/main/app/src/boot/Kconfig)

### Double Tap To Bootloader

Some SoCs, like RP2040 or the various STM32 offerings, require holding a certain "boot button" down to enter the bootloader, on a hardware level. To make it easier to enter the bootloader on those platforms, ZMK integrates an optional feature to allow entering the bootloader by simply double tapping reset within the configured timeout period.

| Config | Type | Description | Default |
| ------------------------------------------ | ---- | ------------------------------------------------------------------- | --------------------------- |
| `CONFIG_ZMK_DBL_TAP_BOOTLOADER` | bool | Enable the double-tap to enter bootloader functionality | y if STM32 or RP2040/RP2350 |
| `CONFIG_ZMK_DBL_TAP_BOOTLOADER_TIMEOUT_MS` | int | Duration (in ms) to wait for a second reset to enter the bootloader | 500 |

### STM32 nBOOT_SEL Option Byte Setup

Some newer STM32 series SoCs, in particular stm32c0 and stm32g0, enable the `nBOOT_SEL` bit of the option bytes by default. This bit prevents entering the system ROM bootloader by holding the BOOT0 pin/button during a reset/startup.

To ensure the BOOT button on keyboard and controllers using these SoCs works as expected after being flashed with ZMK, we check the `nBOOT_SEL` bit on startup and clear it if it is set. Should you _not_ want that functionality, for some reason, this can be disabled.

| Config | Type | Description | Default |
| ----------------------------------------- | ---- | ------------------------------------- | ----------------------- |
| `CONFIG_ZMK_BOOT_STM32_ENFORCE_NBOOT_SEL` | bool | Ensure the `nBOOT_SEL` bit is not set | y if STM32CO or STM32G0 |

### Bootmode Magic Value Mapper

Some target SoCs may use the bootmode magic value mapper for [bootloader integration](docs/development/hardware-integration/bootloader/index.mdx). When doing so, the following configurations are used:

| Config | Type | Description | Default |
| ---------------------------------------------------------------- | ---- | ------------------------------------------------------------------------------------- | ------- |
| `CONFIG_ZMK_BOOTMODE_BOOTLOADER_MAGIC_VALUE` | hex | The magic value to place into retained memory when the bootloader boot mode is set | none |
| `CONFIG_ZMK_BOOTMODE_MAGIC_VALUE_BOOTLOADER_TYPE_TINYUF2` | bool | Used to default the bootloader magic value for the tinyuf2 bootloader | false |
| `CONFIG_ZMK_BOOTMODE_MAGIC_VALUE_BOOTLOADER_TYPE_ADAFRUIT_BOSSA` | bool | Used to default the bootloader magic value for the Adafruit BOSSA (SAMD21) bootloader | false |
| `CONFIG_ZMK_BOOTMODE_MAGIC_VALUE_BOOTLOADER_TYPE_ADAFRUIT_NRF52` | bool | Used to default the bootloader magic value for the Adafruit nRF52 bootloader | false |
7 changes: 0 additions & 7 deletions docs/docs/config/system.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,13 +120,6 @@ Note that `CONFIG_BT_MAX_CONN` and `CONFIG_BT_MAX_PAIRED` should be set to the s
| `CONFIG_ZMK_USB_LOGGING` | bool | Enable USB CDC ACM logging for debugging | n |
| `CONFIG_ZMK_LOG_LEVEL` | int | Log level for ZMK debug messages | 4 |

### Double Tap To Bootloader

| Config | Type | Description | Default |
| ------------------------------------------ | ---- | ------------------------------------------------------------------- | --------------------------- |
| `CONFIG_ZMK_DBL_TAP_BOOTLOADER` | bool | Enable the double-tap to enter bootloader functionality | y if STM32 or RP2040/RP2350 |
| `CONFIG_ZMK_DBL_TAP_BOOTLOADER_TIMEOUT_MS` | int | Duration (in ms) to wait for a second reset to enter the bootloader | 500 |

## Snippets

:::danger
Expand Down
1 change: 1 addition & 0 deletions docs/sidebars.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ module.exports = {
"config/battery",
"config/behaviors",
"config/bluetooth",
"config/bootloader",
"config/combos",
"config/displays",
"config/encoders",
Expand Down