fix: Improve startup time with proper settings loading.

* Avoid doing duplicate calls to setings_load_subtree, which iterates
  NVS fully each time under the hood, and instead use on settings_load
  later in the lifecycle.
This commit is contained in:
Peter Johanson 2024-07-03 02:33:26 -06:00 committed by Pete Johanson
parent f18974e8c4
commit 80173f8ea3
11 changed files with 129 additions and 102 deletions

View file

@ -12,12 +12,16 @@ config ZMK_BEHAVIOR_LOCAL_IDS
if ZMK_BEHAVIOR_LOCAL_IDS if ZMK_BEHAVIOR_LOCAL_IDS
config ZMK_BEHAVIOR_LOCAL_IDS_IN_BINDINGS
bool "Track in behavior bindings"
choice ZMK_BEHAVIOR_LOCAL_ID_TYPE choice ZMK_BEHAVIOR_LOCAL_ID_TYPE
prompt "Local ID Type" prompt "Local ID Type"
config ZMK_BEHAVIOR_LOCAL_ID_TYPE_SETTINGS_TABLE config ZMK_BEHAVIOR_LOCAL_ID_TYPE_SETTINGS_TABLE
bool "Settings Table" bool "Settings Table"
depends on SETTINGS depends on SETTINGS
select ZMK_BEHAVIOR_LOCAL_IDS_IN_BINDINGS
help help
Use persistent entries in the settings subsystem to identify Use persistent entries in the settings subsystem to identify
behaviors by local ID, which uses the device name to generate behaviors by local ID, which uses the device name to generate

View file

@ -11,7 +11,12 @@
#define ZMK_BEHAVIOR_OPAQUE 0 #define ZMK_BEHAVIOR_OPAQUE 0
#define ZMK_BEHAVIOR_TRANSPARENT 1 #define ZMK_BEHAVIOR_TRANSPARENT 1
typedef uint16_t zmk_behavior_local_id_t;
struct zmk_behavior_binding { struct zmk_behavior_binding {
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_LOCAL_IDS_IN_BINDINGS)
zmk_behavior_local_id_t local_id;
#endif // IS_ENABLED(CONFIG_ZMK_BEHAVIOR_LOCAL_IDS_IN_BINDINGS)
const char *behavior_dev; const char *behavior_dev;
uint32_t param1; uint32_t param1;
uint32_t param2; uint32_t param2;
@ -23,8 +28,6 @@ struct zmk_behavior_binding_event {
int64_t timestamp; int64_t timestamp;
}; };
typedef uint16_t zmk_behavior_local_id_t;
/** /**
* @brief Get a const struct device* for a behavior from its @p name field. * @brief Get a const struct device* for a behavior from its @p name field.
* *

View file

@ -58,7 +58,7 @@ static int zmk_backlight_update(void) {
#if IS_ENABLED(CONFIG_SETTINGS) #if IS_ENABLED(CONFIG_SETTINGS)
static int backlight_settings_load_cb(const char *name, size_t len, settings_read_cb read_cb, static int backlight_settings_load_cb(const char *name, size_t len, settings_read_cb read_cb,
void *cb_arg, void *param) { void *cb_arg) {
const char *next; const char *next;
if (settings_name_steq(name, "state", &next) && !next) { if (settings_name_steq(name, "state", &next) && !next) {
if (len != sizeof(state)) { if (len != sizeof(state)) {
@ -66,11 +66,18 @@ static int backlight_settings_load_cb(const char *name, size_t len, settings_rea
} }
int rc = read_cb(cb_arg, &state, sizeof(state)); int rc = read_cb(cb_arg, &state, sizeof(state));
if (rc >= 0) {
rc = zmk_backlight_update();
}
return MIN(rc, 0); return MIN(rc, 0);
} }
return -ENOENT; return -ENOENT;
} }
SETTINGS_STATIC_HANDLER_DEFINE(backlight, "backlight", NULL, backlight_settings_load_cb, NULL,
NULL);
static void backlight_save_work_handler(struct k_work *work) { static void backlight_save_work_handler(struct k_work *work) {
settings_save_one("backlight/state", &state, sizeof(state)); settings_save_one("backlight/state", &state, sizeof(state));
} }
@ -85,11 +92,6 @@ static int zmk_backlight_init(void) {
} }
#if IS_ENABLED(CONFIG_SETTINGS) #if IS_ENABLED(CONFIG_SETTINGS)
settings_subsys_init();
int rc = settings_load_subtree_direct("backlight", backlight_settings_load_cb, NULL);
if (rc != 0) {
LOG_ERR("Failed to load backlight settings: %d", rc);
}
k_work_init_delayable(&backlight_save_work, backlight_save_work_handler); k_work_init_delayable(&backlight_save_work, backlight_save_work_handler);
#endif #endif
#if IS_ENABLED(CONFIG_ZMK_BACKLIGHT_AUTO_OFF_USB) #if IS_ENABLED(CONFIG_ZMK_BACKLIGHT_AUTO_OFF_USB)

View file

@ -229,6 +229,8 @@ static int behavior_local_id_init(void) {
return 0; return 0;
} }
SYS_INIT(behavior_local_id_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
#elif IS_ENABLED(CONFIG_ZMK_BEHAVIOR_LOCAL_ID_TYPE_SETTINGS_TABLE) #elif IS_ENABLED(CONFIG_ZMK_BEHAVIOR_LOCAL_ID_TYPE_SETTINGS_TABLE)
static zmk_behavior_local_id_t largest_local_id = 0; static zmk_behavior_local_id_t largest_local_id = 0;
@ -239,7 +241,7 @@ static int behavior_handle_set(const char *name, size_t len, settings_read_cb re
if (settings_name_steq(name, "local_id", &next) && next) { if (settings_name_steq(name, "local_id", &next) && next) {
char *endptr; char *endptr;
uint8_t local_id = strtoul(next, &endptr, 10); zmk_behavior_local_id_t local_id = strtoul(next, &endptr, 10);
if (*endptr != '\0') { if (*endptr != '\0') {
LOG_WRN("Invalid behavior local ID: %s with endptr %s", next, endptr); LOG_WRN("Invalid behavior local ID: %s with endptr %s", next, endptr);
return -EINVAL; return -EINVAL;
@ -302,22 +304,12 @@ static int behavior_handle_commit(void) {
SETTINGS_STATIC_HANDLER_DEFINE(behavior, "behavior", NULL, behavior_handle_set, SETTINGS_STATIC_HANDLER_DEFINE(behavior, "behavior", NULL, behavior_handle_set,
behavior_handle_commit, NULL); behavior_handle_commit, NULL);
static int behavior_local_id_init(void) {
settings_subsys_init();
settings_load_subtree("behavior");
return 0;
}
#else #else
#error "A behavior local ID mechanism must be selected" #error "A behavior local ID mechanism must be selected"
#endif #endif
SYS_INIT(behavior_local_id_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
#endif #endif
#if IS_ENABLED(CONFIG_LOG) #if IS_ENABLED(CONFIG_LOG)

View file

@ -445,7 +445,11 @@ static int ble_profiles_handle_set(const char *name, size_t len, settings_read_c
return 0; return 0;
}; };
struct settings_handler profiles_handler = {.name = "ble", .h_set = ble_profiles_handle_set}; static int zmk_ble_complete_startup(void);
static struct settings_handler profiles_handler = {
.name = "ble", .h_set = ble_profiles_handle_set, .h_commit = zmk_ble_complete_startup};
#endif /* IS_ENABLED(CONFIG_SETTINGS) */ #endif /* IS_ENABLED(CONFIG_SETTINGS) */
static bool is_conn_active_profile(const struct bt_conn *conn) { static bool is_conn_active_profile(const struct bt_conn *conn) {
@ -644,29 +648,7 @@ static void zmk_ble_ready(int err) {
update_advertising(); update_advertising();
} }
static int zmk_ble_init(void) { static int zmk_ble_complete_startup(void) {
int err = bt_enable(NULL);
if (err) {
LOG_ERR("BLUETOOTH FAILED (%d)", err);
return err;
}
#if IS_ENABLED(CONFIG_SETTINGS)
settings_subsys_init();
err = settings_register(&profiles_handler);
if (err) {
LOG_ERR("Failed to setup the profile settings handler (err %d)", err);
return err;
}
k_work_init_delayable(&ble_save_work, ble_save_profile_work);
settings_load_subtree("ble");
settings_load_subtree("bt");
#endif
#if IS_ENABLED(CONFIG_ZMK_BLE_CLEAR_BONDS_ON_START) #if IS_ENABLED(CONFIG_ZMK_BLE_CLEAR_BONDS_ON_START)
LOG_WRN("Clearing all existing BLE bond information from the keyboard"); LOG_WRN("Clearing all existing BLE bond information from the keyboard");
@ -706,6 +688,24 @@ static int zmk_ble_init(void) {
return 0; return 0;
} }
static int zmk_ble_init(void) {
int err = bt_enable(NULL);
if (err < 0 && err != -EALREADY) {
LOG_ERR("BLUETOOTH FAILED (%d)", err);
return err;
}
#if IS_ENABLED(CONFIG_SETTINGS)
settings_register(&profiles_handler);
k_work_init_delayable(&ble_save_work, ble_save_profile_work);
#else
zmk_ble_complete_startup();
#endif
return 0;
}
#if IS_ENABLED(CONFIG_ZMK_BLE_PASSKEY_ENTRY) #if IS_ENABLED(CONFIG_ZMK_BLE_PASSKEY_ENTRY)
static bool zmk_ble_numeric_usage_to_value(const zmk_key_t key, const zmk_key_t one, static bool zmk_ble_numeric_usage_to_value(const zmk_key_t key, const zmk_key_t one,

View file

@ -263,7 +263,8 @@ static int endpoints_handle_set(const char *name, size_t len, settings_read_cb r
return 0; return 0;
} }
struct settings_handler endpoints_handler = {.name = "endpoints", .h_set = endpoints_handle_set}; SETTINGS_STATIC_HANDLER_DEFINE(endpoints, "endpoints", NULL, endpoints_handle_set, NULL, NULL);
#endif /* IS_ENABLED(CONFIG_SETTINGS) */ #endif /* IS_ENABLED(CONFIG_SETTINGS) */
static bool is_usb_ready(void) { static bool is_usb_ready(void) {
@ -322,17 +323,7 @@ static struct zmk_endpoint_instance get_selected_instance(void) {
static int zmk_endpoints_init(void) { static int zmk_endpoints_init(void) {
#if IS_ENABLED(CONFIG_SETTINGS) #if IS_ENABLED(CONFIG_SETTINGS)
settings_subsys_init();
int err = settings_register(&endpoints_handler);
if (err) {
LOG_ERR("Failed to register the endpoints settings handler (err %d)", err);
return err;
}
k_work_init_delayable(&endpoints_save_work, endpoints_save_preferred_work); k_work_init_delayable(&endpoints_save_work, endpoints_save_preferred_work);
settings_load_subtree("endpoints");
#endif #endif
current_instance = get_selected_instance(); current_instance = get_selected_instance();

View file

@ -121,12 +121,27 @@ static int ext_power_settings_set(const char *name, size_t len, settings_read_cb
return -ENOENT; return -ENOENT;
} }
struct settings_handler ext_power_conf = {.name = "ext_power/state", static int ext_power_settings_commit() {
.h_set = ext_power_settings_set}; const struct device *dev = DEVICE_DT_GET(DT_DRV_INST(0));
struct ext_power_generic_data *data = dev->data;
if (!data->settings_init) {
data->status = true;
k_work_schedule(&ext_power_save_work, K_NO_WAIT);
ext_power_enable(dev);
}
return 0;
}
SETTINGS_STATIC_HANDLER_DEFINE(ext_power, "ext_power/state", NULL, ext_power_settings_set,
ext_power_settings_commit, NULL);
#endif #endif
static int ext_power_generic_init(const struct device *dev) { static int ext_power_generic_init(const struct device *dev) {
struct ext_power_generic_data *data = dev->data;
const struct ext_power_generic_config *config = dev->config; const struct ext_power_generic_config *config = dev->config;
if (gpio_pin_configure_dt(&config->control, GPIO_OUTPUT_INACTIVE)) { if (gpio_pin_configure_dt(&config->control, GPIO_OUTPUT_INACTIVE)) {
@ -135,25 +150,7 @@ static int ext_power_generic_init(const struct device *dev) {
} }
#if IS_ENABLED(CONFIG_SETTINGS) #if IS_ENABLED(CONFIG_SETTINGS)
settings_subsys_init();
int err = settings_register(&ext_power_conf);
if (err) {
LOG_ERR("Failed to register the ext_power settings handler (err %d)", err);
return err;
}
k_work_init_delayable(&ext_power_save_work, ext_power_save_state_work); k_work_init_delayable(&ext_power_save_work, ext_power_save_state_work);
// Set default value (on) if settings isn't set
settings_load_subtree("ext_power");
if (!data->settings_init) {
data->status = true;
k_work_schedule(&ext_power_save_work, K_NO_WAIT);
ext_power_enable(dev);
}
#else #else
// Default to the ext_power being open when no settings // Default to the ext_power being open when no settings
ext_power_enable(dev); ext_power_enable(dev);

View file

@ -24,6 +24,11 @@ int main(void) {
return -ENOTSUP; return -ENOTSUP;
} }
#if IS_ENABLED(CONFIG_SETTINGS)
settings_subsys_init();
settings_load();
#endif
#ifdef CONFIG_ZMK_DISPLAY #ifdef CONFIG_ZMK_DISPLAY
zmk_display_init(); zmk_display_init();
#endif /* CONFIG_ZMK_DISPLAY */ #endif /* CONFIG_ZMK_DISPLAY */

View file

@ -221,6 +221,10 @@ static int rgb_settings_set(const char *name, size_t len, settings_read_cb read_
rc = read_cb(cb_arg, &state, sizeof(state)); rc = read_cb(cb_arg, &state, sizeof(state));
if (rc >= 0) { if (rc >= 0) {
if (state.on) {
k_timer_start(&underglow_tick, K_NO_WAIT, K_MSEC(50));
}
return 0; return 0;
} }
@ -230,7 +234,7 @@ static int rgb_settings_set(const char *name, size_t len, settings_read_cb read_
return -ENOENT; return -ENOENT;
} }
struct settings_handler rgb_conf = {.name = "rgb/underglow", .h_set = rgb_settings_set}; SETTINGS_STATIC_HANDLER_DEFINE(rgb_underglow, "rgb/underglow", NULL, rgb_settings_set, NULL, NULL);
static void zmk_rgb_underglow_save_state_work(struct k_work *_work) { static void zmk_rgb_underglow_save_state_work(struct k_work *_work) {
settings_save_one("rgb/underglow/state", &state, sizeof(state)); settings_save_one("rgb/underglow/state", &state, sizeof(state));
@ -262,17 +266,7 @@ static int zmk_rgb_underglow_init(void) {
}; };
#if IS_ENABLED(CONFIG_SETTINGS) #if IS_ENABLED(CONFIG_SETTINGS)
settings_subsys_init();
int err = settings_register(&rgb_conf);
if (err) {
LOG_ERR("Failed to register the ext_power settings handler (err %d)", err);
return err;
}
k_work_init_delayable(&underglow_save_work, zmk_rgb_underglow_save_state_work); k_work_init_delayable(&underglow_save_work, zmk_rgb_underglow_save_state_work);
settings_load_subtree("rgb/underglow");
#endif #endif
#if IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_USB) #if IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_USB)

View file

@ -12,6 +12,7 @@
#include <zephyr/bluetooth/uuid.h> #include <zephyr/bluetooth/uuid.h>
#include <zephyr/bluetooth/gatt.h> #include <zephyr/bluetooth/gatt.h>
#include <zephyr/bluetooth/hci.h> #include <zephyr/bluetooth/hci.h>
#include <zephyr/settings/settings.h>
#include <zephyr/sys/byteorder.h> #include <zephyr/sys/byteorder.h>
#include <zephyr/logging/log.h> #include <zephyr/logging/log.h>
@ -865,13 +866,34 @@ int zmk_split_bt_update_hid_indicator(zmk_hid_indicators_t indicators) {
#endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS) #endif // IS_ENABLED(CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS)
static int finish_init() {
return IS_ENABLED(CONFIG_ZMK_BLE_CLEAR_BONDS_ON_START) ? 0 : start_scanning();
}
#if IS_ENABLED(CONFIG_SETTINGS)
static int central_ble_handle_set(const char *name, size_t len, settings_read_cb read_cb,
void *cb_arg) {
return 0;
}
static struct settings_handler ble_central_settings_handler = {
.name = "ble_central", .h_set = central_ble_handle_set, .h_commit = finish_init};
#endif // IS_ENABLED(CONFIG_SETTINGS)
static int zmk_split_bt_central_init(void) { static int zmk_split_bt_central_init(void) {
k_work_queue_start(&split_central_split_run_q, split_central_split_run_q_stack, k_work_queue_start(&split_central_split_run_q, split_central_split_run_q_stack,
K_THREAD_STACK_SIZEOF(split_central_split_run_q_stack), K_THREAD_STACK_SIZEOF(split_central_split_run_q_stack),
CONFIG_ZMK_BLE_THREAD_PRIORITY, NULL); CONFIG_ZMK_BLE_THREAD_PRIORITY, NULL);
bt_conn_cb_register(&conn_callbacks); bt_conn_cb_register(&conn_callbacks);
return IS_ENABLED(CONFIG_ZMK_BLE_CLEAR_BONDS_ON_START) ? 0 : start_scanning(); #if IS_ENABLED(CONFIG_SETTINGS)
settings_register(&ble_central_settings_handler);
return 0;
#else
return finish_init();
#endif // IS_ENABLED(CONFIG_SETTINGS)
} }
SYS_INIT(zmk_split_bt_central_init, APPLICATION, CONFIG_ZMK_BLE_INIT_PRIORITY); SYS_INIT(zmk_split_bt_central_init, APPLICATION, CONFIG_ZMK_BLE_INIT_PRIORITY);

View file

@ -146,21 +146,7 @@ bool zmk_split_bt_peripheral_is_connected(void) { return is_connected; }
bool zmk_split_bt_peripheral_is_bonded(void) { return is_bonded; } bool zmk_split_bt_peripheral_is_bonded(void) { return is_bonded; }
static int zmk_peripheral_ble_init(void) { static int zmk_peripheral_ble_complete_startup(void) {
int err = bt_enable(NULL);
if (err) {
LOG_ERR("BLUETOOTH FAILED (%d)", err);
return err;
}
#if IS_ENABLED(CONFIG_SETTINGS)
settings_subsys_init();
settings_load_subtree("ble");
settings_load_subtree("bt");
#endif
#if IS_ENABLED(CONFIG_ZMK_BLE_CLEAR_BONDS_ON_START) #if IS_ENABLED(CONFIG_ZMK_BLE_CLEAR_BONDS_ON_START)
LOG_WRN("Clearing all existing BLE bond information from the keyboard"); LOG_WRN("Clearing all existing BLE bond information from the keyboard");
@ -176,4 +162,35 @@ static int zmk_peripheral_ble_init(void) {
return 0; return 0;
} }
#if IS_ENABLED(CONFIG_SETTINGS)
static int peripheral_ble_handle_set(const char *name, size_t len, settings_read_cb read_cb,
void *cb_arg) {
return 0;
}
static struct settings_handler ble_peripheral_settings_handler = {
.name = "ble_peripheral",
.h_set = peripheral_ble_handle_set,
.h_commit = zmk_peripheral_ble_complete_startup};
#endif // IS_ENABLED(CONFIG_SETTINGS)
static int zmk_peripheral_ble_init(void) {
int err = bt_enable(NULL);
if (err) {
LOG_ERR("BLUETOOTH FAILED (%d)", err);
return err;
}
#if IS_ENABLED(CONFIG_SETTINGS)
settings_register(&ble_peripheral_settings_handler);
#else
zmk_peripheral_ble_complete_startup();
#endif
return 0;
}
SYS_INIT(zmk_peripheral_ble_init, APPLICATION, CONFIG_ZMK_BLE_INIT_PRIORITY); SYS_INIT(zmk_peripheral_ble_init, APPLICATION, CONFIG_ZMK_BLE_INIT_PRIORITY);