Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bootloader/retention boot mode support #2683

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
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
1 change: 1 addition & 0 deletions app/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ zephyr_syscall_header(${APPLICATION_SOURCE_DIR}/include/drivers/ext_power.h)
# Add your source file to the "app" target. This must come after
# find_package(Zephyr) which defines the target.
target_include_directories(app PRIVATE include)
add_subdirectory(src/boot)
target_sources(app PRIVATE src/stdlib.c)
target_sources(app PRIVATE src/activity.c)
target_sources(app PRIVATE src/behavior.c)
Expand Down
2 changes: 2 additions & 0 deletions app/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,8 @@ endmenu

menu "Advanced"

rsource "src/boot/Kconfig"

menu "Initialization Priorities"

if USB_DEVICE_STACK
Expand Down
1 change: 1 addition & 0 deletions app/dts/behaviors/reset.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
bootloader: bootload {
compatible = "zmk,behavior-reset";
type = <RST_UF2>;
bootloader;
#binding-cells = <0>;
display-name = "Bootloader";
};
Expand Down
2 changes: 2 additions & 0 deletions app/dts/bindings/behaviors/zmk,behavior-reset.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,5 @@ properties:
type:
type: int
default: 0
bootloader:
type: boolean
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Copyright (c) 2024 The ZMK Contributors
# SPDX-License-Identifier: MIT

description: |
Driver for mapping bootloader boot mode to a magic value

compatible: "zmk,bootmode-to-magic-mapper"

include: base.yaml
28 changes: 26 additions & 2 deletions app/src/behaviors/behavior_reset.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,21 @@

#include <zmk/behavior.h>

#if IS_ENABLED(CONFIG_RETENTION_BOOT_MODE)

#include <zephyr/retention/bootmode.h>

#endif /* IS_ENABLED(CONFIG_RETENTION_BOOT_MODE) */

LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);

#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
struct behavior_reset_config {
#if IS_ENABLED(CONFIG_RETENTION_BOOT_MODE)
enum BOOT_MODE_TYPES boot_mode;
#else
int type;
#endif /* IS_ENABLED(CONFIG_RETENTION_BOOT_MODE) */
};

static int behavior_reset_init(const struct device *dev) { return 0; };
Expand All @@ -28,10 +38,20 @@ static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
const struct device *dev = zmk_behavior_get_binding(binding->behavior_dev);
const struct behavior_reset_config *cfg = dev->config;

// TODO: Correct magic code for going into DFU?
#if IS_ENABLED(CONFIG_RETENTION_BOOT_MODE)
int ret = bootmode_set(cfg->boot_mode);
if (ret < 0) {
LOG_ERR("Failed to set the bootloader mode (%d)", ret);
return ZMK_BEHAVIOR_OPAQUE;
}

sys_reboot(SYS_REBOOT_WARM);
#else
// See
// https://github.com/adafruit/Adafruit_nRF52_Bootloader/blob/d6b28e66053eea467166f44875e3c7ec741cb471/src/main.c#L107
sys_reboot(cfg->type);
#endif /* IS_ENABLED(CONFIG_RETENTION_BOOT_MODE) */

return ZMK_BEHAVIOR_OPAQUE;
}

Expand All @@ -45,7 +65,11 @@ static const struct behavior_driver_api behavior_reset_driver_api = {

#define RST_INST(n) \
static const struct behavior_reset_config behavior_reset_config_##n = { \
.type = DT_INST_PROP(n, type)}; \
COND_CODE_1( \
IS_ENABLED(CONFIG_RETENTION_BOOT_MODE), \
(DT_INST_PROP(n, bootloader) ? BOOT_MODE_TYPE_BOOTLOADER : BOOT_MODE_TYPE_NORMAL), \
(.type = DT_INST_PROP(n, type))), \
}; \
BEHAVIOR_DT_INST_DEFINE(n, behavior_reset_init, NULL, NULL, &behavior_reset_config_##n, \
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \
&behavior_reset_driver_api);
Expand Down
2 changes: 2 additions & 0 deletions app/src/boot/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

target_sources_ifdef(CONFIG_ZMK_BOOTMODE_TO_MAGIC_VALUE_MAPPER app PRIVATE bootmode_to_magic_mapper.c)
32 changes: 32 additions & 0 deletions app/src/boot/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@

config ZMK_BOOTMODE_TO_MAGIC_VALUE_MAPPER
bool "Magic Value Mapper"
default y
depends on DT_HAS_ZMK_BOOTMODE_TO_MAGIC_MAPPER_ENABLED

if ZMK_BOOTMODE_TO_MAGIC_VALUE_MAPPER

choice ZMK_BOOTMODE_MAGIC_VALUE_BOOTLOADER_TYPE
prompt "Magic Value Bootloader Type"

config ZMK_BOOTMODE_MAGIC_VALUE_BOOTLOADER_TYPE_UNKNOWN
bool "Unknown"

config ZMK_BOOTMODE_MAGIC_VALUE_BOOTLOADER_TYPE_TINYUF2
bool "tinyuf2"

config ZMK_BOOTMODE_MAGIC_VALUE_BOOTLOADER_TYPE_ADAFRUIT_BOSSA
bool "Adafruit BOSSA"


config ZMK_BOOTMODE_MAGIC_VALUE_BOOTLOADER_TYPE_ADAFRUIT_NRF52
bool "Adafruit nRF52"

endchoice

config ZMK_BOOTMODE_BOOTLOADER_MAGIC_VALUE
hex
default 0xf01669ef if ZMK_BOOTMODE_MAGIC_VALUE_BOOTLOADER_TYPE_TINYUF2 || ZMK_BOOTMODE_MAGIC_VALUE_BOOTLOADER_TYPE_ADAFRUIT_BOSSA || BOOTLOADER_BOSSA_ADAFRUIT_UF2
default 0x57 if ZMK_BOOTMODE_MAGIC_VALUE_BOOTLOADER_TYPE_ADAFRUIT_NRF52

endif
55 changes: 55 additions & 0 deletions app/src/boot/bootmode_to_magic_mapper.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright (c) 2024 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/

#define DT_DRV_COMPAT zmk_bootmode_to_magic_mapper

#include <zephyr/device.h>
#include <zephyr/retention/bootmode.h>
#include <zephyr/retention/retention.h>
#include <zephyr/drivers/retained_mem.h>

static const struct device *magic_dev = DEVICE_DT_GET(DT_CHOSEN(zmk_magic_boot_mode));
static const uint32_t bootloader_magic_value = CONFIG_ZMK_BOOTMODE_BOOTLOADER_MAGIC_VALUE;

static ssize_t btmm_ram_size(const struct device *dev) { return (ssize_t)1; }

static int btmm_ram_read(const struct device *dev, off_t offset, uint8_t *buffer, size_t size) {
if (size != 1) {
return -ENOTSUP;
}

uint32_t val;
int ret = retention_read(magic_dev, 0, (uint8_t *)&val, sizeof(val));
if (ret < 0) {
return ret;
}

*buffer = (val == bootloader_magic_value) ? BOOT_MODE_TYPE_BOOTLOADER : BOOT_MODE_TYPE_NORMAL;

return 0;
}

static int btmm_ram_write(const struct device *dev, off_t offset, const uint8_t *buffer,
size_t size) {
if (size != 1) {
return -ENOTSUP;
}

uint32_t val = (*buffer == BOOT_MODE_TYPE_BOOTLOADER) ? bootloader_magic_value : 0;

return retention_write(magic_dev, 0, (uint8_t *)&val, sizeof(val));
}

static int btmm_ram_clear(const struct device *dev) { return retention_clear(magic_dev); }

static const struct retained_mem_driver_api btmm_api = {
.size = btmm_ram_size,
.read = btmm_ram_read,
.write = btmm_ram_write,
.clear = btmm_ram_clear,
};

DEVICE_DT_INST_DEFINE(0, NULL, NULL, NULL, NULL, POST_KERNEL, 0, &btmm_api);
6 changes: 4 additions & 2 deletions app/west.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ manifest:
url-base: https://github.com/zephyrproject-rtos
- name: zmkfirmware
url-base: https://github.com/zmkfirmware
- name: petejohanson
url-base: https://github.com/petejohanson
projects:
- name: zephyr
remote: zmkfirmware
revision: v3.5.0+zmk-fixes
remote: petejohanson
revision: 3.5-stm32-bootloader-support
clone-depth: 1
import:
name-blocklist:
Expand Down
Loading