mirror of
https://github.com/qmk/qmk_firmware.git
synced 2026-06-20 14:23:45 -04:00
Enable modules to persist data (#26201)
This commit is contained in:
@@ -187,9 +187,9 @@ include $(COMMUNITY_RULES_MK)
|
||||
|
||||
ifneq ($(COMMUNITY_MODULES),)
|
||||
|
||||
$(INTERMEDIATE_OUTPUT)/src/community_config.h: $(KEYMAP_JSON) $(DD_CONFIG_FILES)
|
||||
$(INTERMEDIATE_OUTPUT)/src/community_post_config.h: $(KEYMAP_JSON) $(DD_CONFIG_FILES)
|
||||
@$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD)
|
||||
$(eval CMD=$(QMK_BIN) generate-community-config-h -kb $(KEYBOARD) --quiet --output $(INTERMEDIATE_OUTPUT)/src/community_config.h $(KEYMAP_JSON))
|
||||
$(eval CMD=$(QMK_BIN) generate-community-post-config-h -kb $(KEYBOARD) --quiet --output $(INTERMEDIATE_OUTPUT)/src/community_post_config.h $(KEYMAP_JSON))
|
||||
@$(BUILD_CMD)
|
||||
|
||||
$(INTERMEDIATE_OUTPUT)/src/community_modules.h: $(KEYMAP_JSON) $(DD_CONFIG_FILES)
|
||||
@@ -227,10 +227,10 @@ $(INTERMEDIATE_OUTPUT)/src/split_transaction_id_community_modules.inc: $(KEYMAP_
|
||||
$(eval CMD=$(QMK_BIN) generate-split-transaction-id-community-modules-inc -kb $(KEYBOARD) --quiet --output $(INTERMEDIATE_OUTPUT)/src/split_transaction_id_community_modules.inc $(KEYMAP_JSON))
|
||||
@$(BUILD_CMD)
|
||||
|
||||
COMMUNITY_CONFIG_H = $(INTERMEDIATE_OUTPUT)/src/community_config.h
|
||||
COMMUNITY_POST_CONFIG_H = $(INTERMEDIATE_OUTPUT)/src/community_post_config.h
|
||||
SRC += $(INTERMEDIATE_OUTPUT)/src/community_modules.c
|
||||
|
||||
generated-files: $(INTERMEDIATE_OUTPUT)/src/community_config.h $(INTERMEDIATE_OUTPUT)/src/community_modules.h $(INTERMEDIATE_OUTPUT)/src/community_modules.c $(INTERMEDIATE_OUTPUT)/src/community_modules_introspection.c $(INTERMEDIATE_OUTPUT)/src/community_modules_introspection.h $(INTERMEDIATE_OUTPUT)/src/led_matrix_community_modules.inc $(INTERMEDIATE_OUTPUT)/src/rgb_matrix_community_modules.inc $(INTERMEDIATE_OUTPUT)/src/split_transaction_id_community_modules.inc
|
||||
generated-files: $(INTERMEDIATE_OUTPUT)/src/community_post_config.h $(INTERMEDIATE_OUTPUT)/src/community_modules.h $(INTERMEDIATE_OUTPUT)/src/community_modules.c $(INTERMEDIATE_OUTPUT)/src/community_modules_introspection.c $(INTERMEDIATE_OUTPUT)/src/community_modules_introspection.h $(INTERMEDIATE_OUTPUT)/src/led_matrix_community_modules.inc $(INTERMEDIATE_OUTPUT)/src/rgb_matrix_community_modules.inc $(INTERMEDIATE_OUTPUT)/src/split_transaction_id_community_modules.inc
|
||||
|
||||
endif
|
||||
|
||||
@@ -331,10 +331,6 @@ define config_h_community_module_appender
|
||||
endef
|
||||
$(foreach module,$(COMMUNITY_MODULE_PATHS),$(eval $(call config_h_community_module_appender,$(module))))
|
||||
|
||||
ifneq ($(COMMUNITY_CONFIG_H),)
|
||||
CONFIG_H += $(COMMUNITY_CONFIG_H)
|
||||
endif
|
||||
|
||||
ifneq ("$(wildcard $(KEYBOARD_PATH_5)/config.h)","")
|
||||
CONFIG_H += $(KEYBOARD_PATH_5)/config.h
|
||||
endif
|
||||
@@ -376,6 +372,10 @@ ifneq ("$(wildcard $(KEYBOARD_PATH_5)/post_config.h)","")
|
||||
POST_CONFIG_H += $(KEYBOARD_PATH_5)/post_config.h
|
||||
endif
|
||||
|
||||
ifneq ($(COMMUNITY_POST_CONFIG_H),)
|
||||
POST_CONFIG_H += $(COMMUNITY_POST_CONFIG_H)
|
||||
endif
|
||||
|
||||
CONFIG_H += $(INTERMEDIATE_OUTPUT)/src/info_config.h
|
||||
KEYBOARD_SRC += $(INTERMEDIATE_OUTPUT)/src/default_keyboard.c
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
// This version exists to signify addition of eeconfig support.
|
||||
}
|
||||
@@ -135,28 +135,45 @@ This file defines LED matrix effects in the same form as used with `led_matrix_k
|
||||
|
||||
This file defines RGB matrix effects in the same form as used with `rgb_matrix_kb.inc` and `rgb_matrix_user.inc` (see [Custom RGB Matrix Effects](rgb_matrix#custom-rgb-matrix-effects)). Effect mode names are prepended with `RGB_MATRIX_COMMUNITY_MODULE_`.
|
||||
|
||||
### Custom split keyboard data sync
|
||||
### Additional Customization
|
||||
|
||||
Defines follow the convention, `SPLIT_TRANSACTION_IDS_MODULE_<MODULE>` (see [Custom data sync](split_keyboard#custom-data-sync)).
|
||||
#### Split Keyboard Data Sync
|
||||
|
||||
Defines follow the convention, `SPLIT_TRANSACTION_IDS_MODULE_<MODULE>` (see [Custom data sync](split_keyboard#custom-data-sync)).
|
||||
|
||||
#### Persistent Configuration
|
||||
|
||||
Defines follow the convention, `EECONFIG_MODULE_<MODULE>_DATA_SIZE` and `EECONFIG_MODULE_<MODULE>_DATA_VERSION` (see [Custom Persistent Configuration](../feature_eeprom#datablock)).
|
||||
|
||||
When configured, the following APIs are available:
|
||||
|
||||
| API Format | Example (`hello_world` module) | API Version |
|
||||
|--------------------------------------------|-----------------------------------------------|-------------|
|
||||
| `eeconfig_is_<module>_datablock_valid` | `eeconfig_is_hello_world_datablock_valid` | `1.1.3` |
|
||||
| `eeconfig_read_<module>_datablock` | `eeconfig_read_hello_world_datablock` | `1.1.3` |
|
||||
| `eeconfig_update_<module>_datablock` | `eeconfig_update_hello_world_datablock` | `1.1.3` |
|
||||
| `eeconfig_init_<module>_datablock` | `eeconfig_init_hello_world_datablock` | `1.1.3` |
|
||||
| `eeconfig_read_<module>_datablock_field` | `eeconfig_read_hello_world_datablock_field` | `1.1.3` |
|
||||
| `eeconfig_update_<module>_datablock_field` | `eeconfig_update_hello_world_datablock_field` | `1.1.3` |
|
||||
|
||||
### Compatible APIs
|
||||
|
||||
Community Modules may provide specializations for the following APIs:
|
||||
|
||||
| Base API | API Format | Example (`hello_world` module) | API Version |
|
||||
|----------------------------------|-------------------------------------------|---------------------------------------------|-------------|
|
||||
| `keyboard_pre_init` | `keyboard_pre_init_<module>` | `keyboard_pre_init_hello_world` | `0.1.0` |
|
||||
| `keyboard_post_init` | `keyboard_post_init_<module>` | `keyboard_post_init_hello_world` | `0.1.0` |
|
||||
| `pre_process_record` | `pre_process_record_<module>` | `pre_process_record_hello_world` | `0.1.0` |
|
||||
| `process_record` | `process_record_<module>` | `process_record_hello_world` | `0.1.0` |
|
||||
| `post_process_record` | `post_process_record_<module>` | `post_process_record_hello_world` | `0.1.0` |
|
||||
| `housekeeping_task` | `housekeeping_task_<module>` | `housekeeping_task_hello_world` | `1.0.0` |
|
||||
| `suspend_power_down` | `suspend_power_down_<module>` | `suspend_power_down_hello_world` | `1.0.0` |
|
||||
| `suspend_wakeup_init` | `suspend_wakeup_init_<module>` | `suspend_wakeup_init_hello_world` | `1.0.0` |
|
||||
| `shutdown` | `shutdown_<module>` | `shutdown_hello_world` | `1.0.0` |
|
||||
| `process_detected_host_os` | `process_detected_host_os_<module>` | `process_detected_host_os_hello_world` | `1.0.0` |
|
||||
| `default_layer_state_set` | `default_layer_state_set_<module>` | `default_layer_state_set_hello_world` | `1.1.0` |
|
||||
| `layer_state_set` | `layer_state_set_<module>` | `layer_state_set_hello_world` | `1.1.0` |
|
||||
| Base API | API Format | Example (`hello_world` module) | API Version |
|
||||
|----------------------------------|-------------------------------------------|----------------------------------------------|-------------|
|
||||
| `keyboard_pre_init` | `keyboard_pre_init_<module>` | `keyboard_pre_init_hello_world` | `0.1.0` |
|
||||
| `keyboard_post_init` | `keyboard_post_init_<module>` | `keyboard_post_init_hello_world` | `0.1.0` |
|
||||
| `pre_process_record` | `pre_process_record_<module>` | `pre_process_record_hello_world` | `0.1.0` |
|
||||
| `process_record` | `process_record_<module>` | `process_record_hello_world` | `0.1.0` |
|
||||
| `post_process_record` | `post_process_record_<module>` | `post_process_record_hello_world` | `0.1.0` |
|
||||
| `housekeeping_task` | `housekeeping_task_<module>` | `housekeeping_task_hello_world` | `1.0.0` |
|
||||
| `suspend_power_down` | `suspend_power_down_<module>` | `suspend_power_down_hello_world` | `1.0.0` |
|
||||
| `suspend_wakeup_init` | `suspend_wakeup_init_<module>` | `suspend_wakeup_init_hello_world` | `1.0.0` |
|
||||
| `shutdown` | `shutdown_<module>` | `shutdown_hello_world` | `1.0.0` |
|
||||
| `process_detected_host_os` | `process_detected_host_os_<module>` | `process_detected_host_os_hello_world` | `1.0.0` |
|
||||
| `default_layer_state_set` | `default_layer_state_set_<module>` | `default_layer_state_set_hello_world` | `1.1.0` |
|
||||
| `layer_state_set` | `layer_state_set_<module>` | `layer_state_set_hello_world` | `1.1.0` |
|
||||
| `led_matrix_indicators` | `led_matrix_indicators_<module>` | `led_matrix_indicators_hello_world` | `1.1.0` |
|
||||
| `led_matrix_indicators_advanced` | `led_matrix_indicators_advanced_<module>` | `led_matrix_indicators_advanced_hello_world` | `1.1.0` |
|
||||
| `rgb_matrix_indicators` | `rgb_matrix_indicators_<module>` | `rgb_matrix_indicators_hello_world` | `1.1.0` |
|
||||
@@ -164,7 +181,6 @@ Community Modules may provide specializations for the following APIs:
|
||||
| `pointing_device_init` | `pointing_device_init_<module>` | `pointing_device_init_hello_world` | `1.1.0` |
|
||||
| `pointing_device_task` | `pointing_device_task_<module>` | `pointing_device_task_hello_world` | `1.1.0` |
|
||||
|
||||
|
||||
::: info
|
||||
An unspecified API is disregarded if a Community Module does not provide a specialization for it.
|
||||
:::
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
// Copyright 2026 QMK
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#include QMK_KEYBOARD_H
|
||||
|
||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {LAYOUT_ortho_1x1(KC_A)};
|
||||
|
||||
void keyboard_post_init_user(void) {
|
||||
// Customise these values to desired behaviour
|
||||
debug_enable = true;
|
||||
debug_matrix = true;
|
||||
// debug_keyboard=true;
|
||||
// debug_mouse=true;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"config": {
|
||||
"features": {
|
||||
"console": true
|
||||
}
|
||||
},
|
||||
"modules": [
|
||||
"qmk/nvm_test"
|
||||
]
|
||||
}
|
||||
@@ -169,6 +169,139 @@ def _generate_modules_rules(keyboard, filename):
|
||||
return lines
|
||||
|
||||
|
||||
def _module_slugs(modules):
|
||||
return [Path(m).name.lower() for m in modules]
|
||||
|
||||
|
||||
def _render_eeconfig_declarations(modules):
|
||||
lines = []
|
||||
lines.append('')
|
||||
lines.append('// nvm eeconfig')
|
||||
for module_slug in _module_slugs(modules):
|
||||
lines.extend([
|
||||
f'#if (EECONFIG_MODULE_{module_slug.upper()}_DATA_SIZE) > 0',
|
||||
f'bool eeconfig_is_{module_slug}_datablock_valid(void);',
|
||||
f'uint32_t eeconfig_read_{module_slug}_datablock(void *data, uint32_t offset, uint32_t length) __attribute__((nonnull));',
|
||||
f'uint32_t eeconfig_update_{module_slug}_datablock(const void *data, uint32_t offset, uint32_t length) __attribute__((nonnull));',
|
||||
f'void eeconfig_init_{module_slug}_datablock(void);',
|
||||
f'# define eeconfig_read_{module_slug}_datablock_field(__object, __field) eeconfig_read_{module_slug}_datablock(&(__object.__field), offsetof(typeof(__object), __field), sizeof(__object.__field))',
|
||||
f'# define eeconfig_update_{module_slug}_datablock_field(__object, __field) eeconfig_update_{module_slug}_datablock(&(__object.__field), offsetof(typeof(__object), __field), sizeof(__object.__field))',
|
||||
'',
|
||||
f'bool nvm_eeconfig_is_{module_slug}_datablock_valid(void);',
|
||||
f'uint32_t nvm_eeconfig_read_{module_slug}_datablock(void *data, uint32_t offset, uint32_t length);',
|
||||
f'uint32_t nvm_eeconfig_update_{module_slug}_datablock(const void *data, uint32_t offset, uint32_t length);',
|
||||
f'void nvm_eeconfig_init_{module_slug}_datablock(void);',
|
||||
f'#endif // (EECONFIG_MODULE_{module_slug.upper()}_DATA_SIZE) > 0',
|
||||
'',
|
||||
])
|
||||
|
||||
lines.append('typedef struct PACKED {')
|
||||
for module_slug in _module_slugs(modules):
|
||||
lines.extend([
|
||||
f'#if (EECONFIG_MODULE_{module_slug.upper()}_DATA_SIZE) > 0',
|
||||
f' uint32_t {module_slug}_version;',
|
||||
f' uint8_t {module_slug}[EECONFIG_MODULE_{module_slug.upper()}_DATA_SIZE];',
|
||||
f'#endif // (EECONFIG_MODULE_{module_slug.upper()}_DATA_SIZE) > 0',
|
||||
])
|
||||
lines.append('} eeprom_modules_t;')
|
||||
lines.append('')
|
||||
|
||||
for module_slug in _module_slugs(modules):
|
||||
lines.append(f'#define EECONFIG_MODULE_{module_slug.upper()}_VERSION (uint32_t *)(EECONFIG_MODULES_DATABLOCK + (offsetof(eeprom_modules_t, {module_slug}_version)))')
|
||||
lines.append(f'#define EECONFIG_MODULE_{module_slug.upper()}_DATABLOCK (uint8_t *)(EECONFIG_MODULES_DATABLOCK + (offsetof(eeprom_modules_t, {module_slug})))')
|
||||
lines.append('')
|
||||
|
||||
lines.append('bool eeconfig_is_modules_datablock_valid(void);')
|
||||
lines.append('void eeconfig_init_modules_datablock(void);')
|
||||
lines.append('')
|
||||
|
||||
return lines
|
||||
|
||||
|
||||
def _render_eeconfig_implementation(modules):
|
||||
lines = []
|
||||
|
||||
lines.append('')
|
||||
lines.append('// nvm eeconfig')
|
||||
lines.append('#if defined(NVM_DRIVER_EEPROM)'),
|
||||
lines.append('# include "nvm_eeprom_eeconfig_internal.h"')
|
||||
lines.append('# include "eeprom.h"')
|
||||
lines.append('#endif // defined(NVM_DRIVER_EEPROM)'),
|
||||
lines.append('')
|
||||
|
||||
for module_slug in _module_slugs(modules):
|
||||
lines.extend([
|
||||
f'#if (EECONFIG_MODULE_{module_slug.upper()}_DATA_SIZE) > 0',
|
||||
f'bool eeconfig_is_{module_slug}_datablock_valid(void) {{ return nvm_eeconfig_is_{module_slug}_datablock_valid(); }}',
|
||||
f'uint32_t eeconfig_read_{module_slug}_datablock(void *data, uint32_t offset, uint32_t length) {{ return nvm_eeconfig_read_{module_slug}_datablock(data, offset, length); }}',
|
||||
f'uint32_t eeconfig_update_{module_slug}_datablock(const void *data, uint32_t offset, uint32_t length) {{ return nvm_eeconfig_update_{module_slug}_datablock(data, offset, length); }}',
|
||||
f'void eeconfig_init_{module_slug}_datablock(void) {{ nvm_eeconfig_init_{module_slug}_datablock(); }}',
|
||||
'',
|
||||
'# if defined(NVM_DRIVER_EEPROM)',
|
||||
f'bool nvm_eeconfig_is_{module_slug}_datablock_valid(void) {{',
|
||||
f' return eeprom_read_dword(EECONFIG_MODULE_{module_slug.upper()}_VERSION) == (EECONFIG_MODULE_{module_slug.upper()}_DATA_VERSION);',
|
||||
'}',
|
||||
f'uint32_t nvm_eeconfig_read_{module_slug}_datablock(void *data, uint32_t offset, uint32_t length) {{',
|
||||
f' if (eeconfig_is_{module_slug}_datablock_valid()) {{',
|
||||
f' void *ee_start = (void *)(uintptr_t)(EECONFIG_MODULE_{module_slug.upper()}_DATABLOCK + offset);',
|
||||
f' void *ee_end = (void *)(uintptr_t)(EECONFIG_MODULE_{module_slug.upper()}_DATABLOCK + MIN((EECONFIG_MODULE_{module_slug.upper()}_DATA_SIZE), offset + length));',
|
||||
' eeprom_read_block(data, ee_start, ee_end - ee_start);',
|
||||
' return ee_end - ee_start;',
|
||||
' } else {',
|
||||
' memset(data, 0, length);',
|
||||
' return length;',
|
||||
' }',
|
||||
'}',
|
||||
f'uint32_t nvm_eeconfig_update_{module_slug}_datablock(const void *data, uint32_t offset, uint32_t length) {{',
|
||||
f' eeprom_update_dword(EECONFIG_MODULE_{module_slug.upper()}_VERSION, (EECONFIG_MODULE_{module_slug.upper()}_DATA_VERSION));',
|
||||
f' void *ee_start = (void *)(uintptr_t)(EECONFIG_MODULE_{module_slug.upper()}_DATABLOCK + offset);',
|
||||
f' void *ee_end = (void *)(uintptr_t)(EECONFIG_MODULE_{module_slug.upper()}_DATABLOCK + MIN((EECONFIG_MODULE_{module_slug.upper()}_DATA_SIZE), offset + length));',
|
||||
' eeprom_update_block(data, ee_start, ee_end - ee_start);',
|
||||
' return ee_end - ee_start;',
|
||||
'}',
|
||||
f'void nvm_eeconfig_init_{module_slug}_datablock(void) {{',
|
||||
f' eeprom_update_dword(EECONFIG_MODULE_{module_slug.upper()}_VERSION, (EECONFIG_MODULE_{module_slug.upper()}_DATA_VERSION));',
|
||||
f' void *start = (void *)(uintptr_t)(EECONFIG_MODULE_{module_slug.upper()}_DATABLOCK);',
|
||||
f' void *end = (void *)(uintptr_t)(EECONFIG_MODULE_{module_slug.upper()}_DATABLOCK + (EECONFIG_MODULE_{module_slug.upper()}_DATA_SIZE));',
|
||||
' long remaining = end - start;',
|
||||
' uint8_t dummy[16] = {0};',
|
||||
f' for (int i = 0; i < EECONFIG_MODULE_{module_slug.upper()}_DATA_SIZE; i += sizeof(dummy)) {{',
|
||||
' int this_loop = remaining < sizeof(dummy) ? remaining : sizeof(dummy);',
|
||||
' eeprom_update_block(dummy, start, this_loop);',
|
||||
' start += this_loop;',
|
||||
' remaining -= this_loop;',
|
||||
' }',
|
||||
'}',
|
||||
'# endif // defined(NVM_DRIVER_EEPROM)',
|
||||
f'#endif // (EECONFIG_MODULE_{module_slug.upper()}_DATA_SIZE) > 0',
|
||||
'',
|
||||
])
|
||||
|
||||
lines.append('bool eeconfig_is_modules_datablock_valid(void) {')
|
||||
lines.append(' return true')
|
||||
for module_slug in _module_slugs(modules):
|
||||
lines.extend([
|
||||
f'#if (EECONFIG_MODULE_{module_slug.upper()}_DATA_SIZE) > 0',
|
||||
f' && eeconfig_is_{module_slug}_datablock_valid()',
|
||||
f'#endif // (EECONFIG_MODULE_{module_slug.upper()}_DATA_SIZE) > 0',
|
||||
])
|
||||
lines.append(' ;')
|
||||
lines.append('}')
|
||||
lines.append('')
|
||||
|
||||
lines.append('void eeconfig_init_modules_datablock(void) {'),
|
||||
for module_slug in _module_slugs(modules):
|
||||
lines.extend([
|
||||
f'#if (EECONFIG_MODULE_{module_slug.upper()}_DATA_SIZE) > 0',
|
||||
f' eeconfig_init_{module_slug}_datablock();',
|
||||
f'#endif // (EECONFIG_MODULE_{module_slug.upper()}_DATA_SIZE) > 0',
|
||||
])
|
||||
lines.append('}')
|
||||
lines.append('')
|
||||
|
||||
return lines
|
||||
|
||||
|
||||
@cli.argument('-o', '--output', arg_only=True, type=qmk.path.normpath, help='File to write to')
|
||||
@cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages")
|
||||
@cli.argument('-e', '--escape', arg_only=True, action='store_true', help="Escape spaces in quiet mode")
|
||||
@@ -196,11 +329,11 @@ def generate_community_modules_rules_mk(cli):
|
||||
|
||||
@cli.argument('-o', '--output', arg_only=True, type=qmk.path.normpath, help='File to write to')
|
||||
@cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages")
|
||||
@cli.argument('-kb', '--keyboard', arg_only=True, type=keyboard_folder, completer=keyboard_completer, help='Keyboard to generate community_config.h for.')
|
||||
@cli.argument('-kb', '--keyboard', arg_only=True, type=keyboard_folder, completer=keyboard_completer, help='Keyboard to generate community_post_config.h for.')
|
||||
@cli.argument('filename', nargs='?', type=qmk.path.FileType('r'), arg_only=True, completer=FilesCompleter('.json'), help='Configurator JSON file')
|
||||
@cli.subcommand('Creates a community_config.h from a keymap.json file.')
|
||||
def generate_community_config_h(cli):
|
||||
"""Creates a community_config.h from a keymap.json file
|
||||
@cli.subcommand('Creates a community_post_config.h from a keymap.json file.')
|
||||
def generate_community_post_config_h(cli):
|
||||
"""Creates a community_post_config.h from a keymap.json file
|
||||
"""
|
||||
if cli.args.output and cli.args.output.name == '-':
|
||||
cli.args.output = None
|
||||
@@ -215,14 +348,29 @@ def generate_community_config_h(cli):
|
||||
modules = get_modules(cli.args.keyboard, cli.args.filename)
|
||||
if len(modules) > 0:
|
||||
lines.append('// Split transactions')
|
||||
for module in modules:
|
||||
for module_slug in _module_slugs(modules):
|
||||
lines.extend([
|
||||
f'#ifdef SPLIT_TRANSACTION_IDS_MODULE_{Path(module).name.upper()}',
|
||||
f'#ifdef SPLIT_TRANSACTION_IDS_MODULE_{module_slug.upper()}',
|
||||
'# define SPLIT_TRANSACTION_RPC',
|
||||
'#endif',
|
||||
])
|
||||
lines.append('')
|
||||
|
||||
lines.append('// nvm eeconfig')
|
||||
for module_slug in _module_slugs(modules):
|
||||
lines.extend([
|
||||
f'#ifndef EECONFIG_MODULE_{module_slug.upper()}_DATA_SIZE',
|
||||
f'# define EECONFIG_MODULE_{module_slug.upper()}_DATA_SIZE 0',
|
||||
'#endif',
|
||||
f'#ifndef EECONFIG_MODULE_{module_slug.upper()}_DATA_VERSION',
|
||||
f'# define EECONFIG_MODULE_{module_slug.upper()}_DATA_VERSION (EECONFIG_MODULE_{module_slug.upper()}_DATA_SIZE)',
|
||||
'#endif',
|
||||
'',
|
||||
])
|
||||
module_size = " + ".join([f'(4 + (EECONFIG_MODULE_{module_slug.upper()}_DATA_SIZE))' for module_slug in _module_slugs(modules)])
|
||||
lines.append(f'#define EECONFIG_MODULE_DATA_SIZE ({module_size})')
|
||||
lines.append('')
|
||||
|
||||
dump_lines(cli.args.output, lines, cli.args.quiet, remove_repeated_newlines=True)
|
||||
|
||||
|
||||
@@ -245,6 +393,7 @@ def generate_community_modules_h(cli):
|
||||
'#pragma once',
|
||||
'#include <stdint.h>',
|
||||
'#include <stdbool.h>',
|
||||
'#include <string.h>',
|
||||
'#include <keycodes.h>',
|
||||
'',
|
||||
'#include "compiler_support.h"',
|
||||
@@ -272,6 +421,8 @@ def generate_community_modules_h(cli):
|
||||
lines.extend(_render_api_declarations(api, Path(module).name))
|
||||
lines.append('')
|
||||
|
||||
lines.extend(_render_eeconfig_declarations(modules))
|
||||
|
||||
lines.append('// Core wrapper')
|
||||
for api in api_list:
|
||||
lines.extend(_render_api_declarations(api, 'modules', user_kb=False))
|
||||
@@ -309,6 +460,8 @@ def generate_community_modules_c(cli):
|
||||
for api in api_list:
|
||||
lines.extend(_render_core_implementation(api, modules))
|
||||
|
||||
lines.extend(_render_eeconfig_implementation(modules))
|
||||
|
||||
dump_lines(cli.args.output, lines, cli.args.quiet, remove_repeated_newlines=True)
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
// Copyright 2026 QMK
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#pragma once
|
||||
|
||||
#define EECONFIG_MODULE_NVM_TEST_DATA_SIZE 4
|
||||
@@ -0,0 +1,53 @@
|
||||
// Copyright 2026 QMK
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#include <stdint.h>
|
||||
#include "community_modules.h"
|
||||
#include "debug.h"
|
||||
#include "timer.h"
|
||||
#include "eeconfig.h"
|
||||
|
||||
ASSERT_COMMUNITY_MODULES_MIN_API_VERSION(1, 1, 3);
|
||||
|
||||
typedef struct my_config_t {
|
||||
uint32_t data;
|
||||
} my_config_t;
|
||||
|
||||
static my_config_t config;
|
||||
|
||||
// Helpers required to bind to debounce helper
|
||||
void eeconfig_read_my_config(my_config_t *value) {
|
||||
eeconfig_read_nvm_test_datablock(value, 0, sizeof(my_config_t));
|
||||
}
|
||||
void eeconfig_update_my_config(my_config_t *value) {
|
||||
eeconfig_update_nvm_test_datablock(value, 0, sizeof(my_config_t));
|
||||
}
|
||||
|
||||
EECONFIG_DEBOUNCE_HELPER(my_config, config);
|
||||
|
||||
void keyboard_post_init_nvm_test(void) {
|
||||
if (!eeconfig_is_nvm_test_datablock_valid()) {
|
||||
eeconfig_init_nvm_test_datablock();
|
||||
}
|
||||
|
||||
eeconfig_init_my_config();
|
||||
}
|
||||
|
||||
bool process_record_nvm_test(uint16_t keycode, keyrecord_t *record) {
|
||||
if (!record->event.pressed) {
|
||||
config.data += 1;
|
||||
eeconfig_flag_my_config(true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void housekeeping_task_nvm_test(void) {
|
||||
eeconfig_flush_my_config(false);
|
||||
|
||||
static uint32_t last_sync = 0;
|
||||
if (timer_elapsed32(last_sync) > 1000) {
|
||||
last_sync = timer_read32();
|
||||
|
||||
dprintf("Config: %ld\n", config.data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"module_name": "Example nvm persistence",
|
||||
"maintainer": "QMK Maintainers",
|
||||
"license": "GPL-2.0-or-later"
|
||||
}
|
||||
@@ -39,6 +39,10 @@
|
||||
# include "connection.h"
|
||||
#endif // CONNECTION_ENABLE
|
||||
|
||||
#ifdef COMMUNITY_MODULES_ENABLE
|
||||
# include "community_modules.h"
|
||||
#endif
|
||||
|
||||
#ifdef VIA_ENABLE
|
||||
bool via_eeprom_is_valid(void);
|
||||
void via_eeprom_set_valid(bool valid);
|
||||
@@ -148,6 +152,10 @@ void eeconfig_init_quantum(void) {
|
||||
eeconfig_init_user_datablock();
|
||||
#endif // (EECONFIG_USER_DATA_SIZE) > 0
|
||||
|
||||
#ifdef COMMUNITY_MODULES_ENABLE
|
||||
eeconfig_init_modules_datablock();
|
||||
#endif // COMMUNITY_MODULES_ENABLE
|
||||
|
||||
#if defined(VIA_ENABLE)
|
||||
// Invalidate VIA eeprom config, and then reset.
|
||||
// Just in case if power is lost mid init, this makes sure that it gets
|
||||
|
||||
@@ -56,8 +56,14 @@ typedef struct PACKED {
|
||||
|
||||
#define EECONFIG_KB_DATABLOCK ((uint8_t *)(EECONFIG_BASE_SIZE))
|
||||
#define EECONFIG_USER_DATABLOCK ((uint8_t *)((EECONFIG_BASE_SIZE) + (EECONFIG_KB_DATA_SIZE)))
|
||||
#define EECONFIG_MODULES_DATABLOCK ((uint8_t *)((EECONFIG_BASE_SIZE) + (EECONFIG_KB_DATA_SIZE) + (EECONFIG_USER_DATA_SIZE)))
|
||||
|
||||
// Actual value is injected via the generated community_post_config.h
|
||||
#ifndef EECONFIG_MODULE_DATA_SIZE
|
||||
# define EECONFIG_MODULE_DATA_SIZE 0
|
||||
#endif
|
||||
|
||||
// Size of EEPROM being used, other code can refer to this for available EEPROM
|
||||
#define EECONFIG_SIZE ((EECONFIG_BASE_SIZE) + (EECONFIG_KB_DATA_SIZE) + (EECONFIG_USER_DATA_SIZE))
|
||||
#define EECONFIG_SIZE ((EECONFIG_BASE_SIZE) + (EECONFIG_KB_DATA_SIZE) + (EECONFIG_USER_DATA_SIZE) + (EECONFIG_MODULE_DATA_SIZE))
|
||||
|
||||
STATIC_ASSERT((intptr_t)EECONFIG_HANDEDNESS == 14, "EEPROM handedness offset is incorrect");
|
||||
|
||||
Reference in New Issue
Block a user