From e12d5d8134c680bc03dfffc44072fc35fb51ff40 Mon Sep 17 00:00:00 2001 From: Dominic Clifton Date: Tue, 20 Jan 2026 16:19:17 +0100 Subject: [PATCH 1/2] Add an `mcu_reset` impl for the kiibohd bootloader. * fixing resetting not working on the Ergodox Infinity. --- platforms/chibios/bootloaders/kiibohd.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/platforms/chibios/bootloaders/kiibohd.c b/platforms/chibios/bootloaders/kiibohd.c index 09a4d49b7871..eb61cd2d0a25 100644 --- a/platforms/chibios/bootloaders/kiibohd.c +++ b/platforms/chibios/bootloaders/kiibohd.c @@ -30,4 +30,21 @@ __attribute__((weak)) void bootloader_jump(void) { // request reset SCB->AIRCR = SCB_AIRCR_VECTKEY_WRITEMAGIC | SCB_AIRCR_SYSRESETREQ_Msk; } -__attribute__((weak)) void mcu_reset(void) {} + +__attribute__((weak)) void mcu_reset(void) { + /* Ensure all outstanding memory operations complete */ + __DSB(); + __ISB(); + + /* Request system reset (preserve PRIGROUP) */ + uint32_t aircr = SCB->AIRCR; + aircr &= ~SCB_AIRCR_VECTKEY_Msk; + aircr |= SCB_AIRCR_VECTKEY_WRITEMAGIC; + aircr |= SCB_AIRCR_SYSRESETREQ_Msk; + SCB->AIRCR = aircr; + + /* Wait for reset to occur */ + while (true) { + __NOP(); + } +} From 5a15dbe74c57f7072b44b544a28f596a223258c9 Mon Sep 17 00:00:00 2001 From: Dominic Clifton Date: Tue, 20 Jan 2026 16:21:46 +0100 Subject: [PATCH 2/2] Handle split keyboard watchdog and os detection resets in a unified way. * reset delegated to the main task. * user code from `pre_mcu_reset_user` is executed before a reset. --- quantum/keyboard.c | 14 ++++++++++++++ quantum/os_detection.c | 20 ++++++++++++-------- quantum/os_detection.h | 2 ++ quantum/quantum.h | 1 + quantum/split_common/split_util.c | 12 ++++++++---- quantum/split_common/split_util.h | 1 + 6 files changed, 38 insertions(+), 12 deletions(-) diff --git a/quantum/keyboard.c b/quantum/keyboard.c index e0c937316564..44399e6e3054 100644 --- a/quantum/keyboard.c +++ b/quantum/keyboard.c @@ -34,6 +34,8 @@ along with this program. If not, see . #include "eeconfig.h" #include "action_layer.h" #include "suspend.h" +#include "bootloader.h" + #ifdef BOOTMAGIC_ENABLE # include "bootmagic.h" #endif @@ -426,6 +428,8 @@ void housekeeping_task(void) { housekeeping_task_user(); } +__attribute__((weak)) void pre_mcu_reset_user(void) {} + /** \brief quantum_init * * Init global state @@ -709,6 +713,9 @@ void quantum_task(void) { /** \brief Main task that is repeatedly called as fast as possible. */ void keyboard_task(void) { + // defer a reset until the end of this task, to allow user-code, leds and screen to update before resetting. + uint8_t reset_pending = false; + __attribute__((unused)) bool activity_has_occurred = false; if (matrix_task()) { last_matrix_activity_trigger(); @@ -719,6 +726,7 @@ void keyboard_task(void) { #if defined(SPLIT_WATCHDOG_ENABLE) split_watchdog_task(); + reset_pending |= split_mcu_reset_is_pending(); #endif #if defined(RGBLIGHT_ENABLE) @@ -801,5 +809,11 @@ void keyboard_task(void) { #ifdef OS_DETECTION_ENABLE os_detection_task(); + reset_pending |= os_detection_mcu_reset_is_pending(); #endif + + if (reset_pending) { + pre_mcu_reset_user(); + mcu_reset(); + } } diff --git a/quantum/os_detection.c b/quantum/os_detection.c index 2a5237dfc31b..79da041efcf0 100644 --- a/quantum/os_detection.c +++ b/quantum/os_detection.c @@ -18,9 +18,6 @@ #include #include "timer.h" -#ifdef OS_DETECTION_KEYBOARD_RESET -# include "quantum.h" -#endif #ifdef OS_DETECTION_DEBUG_ENABLE # include "nvm_eeprom_eeconfig_internal.h" @@ -85,14 +82,10 @@ bool process_detected_host_os_modules(os_variant_t os); void os_detection_task(void) { #ifdef OS_DETECTION_KEYBOARD_RESET - // resetting the keyboard on the USB device state change callback results in instability, so delegate that to this task - if (reset_pending) { - soft_reset_keyboard(); - } // reset the keyboard if it is stuck in the init state for longer than debounce duration, which can happen with some KVMs if (current_usb_device_state.configure_state <= USB_DEVICE_STATE_INIT && maxprev_usb_device_state.configure_state >= USB_DEVICE_STATE_CONFIGURED) { if (debouncing && timer_elapsed_fast(last_time) >= OS_DETECTION_DEBOUNCE) { - soft_reset_keyboard(); + reset_pending = true; } return; } @@ -206,6 +199,8 @@ void os_detection_notify_usb_device_state_change(struct usb_device_state usb_dev } else if (current_usb_device_state.configure_state == USB_DEVICE_STATE_INIT) { // reset the keyboard only if it's been stable for at least debounce duration, to avoid issues with some KVMs if (configured_since > 0 && timer_elapsed_fast(configured_since) >= OS_DETECTION_RESET_DEBOUNCE) { + // resetting the keyboard on the USB device state change callback results in instability + // so set a flag to be checked later reset_pending = true; } configured_since = 0; @@ -213,6 +208,15 @@ void os_detection_notify_usb_device_state_change(struct usb_device_state usb_dev #endif } +bool os_detection_mcu_reset_is_pending(void) { +#ifdef OS_DETECTION_KEYBOARD_RESET + return reset_pending; +#else + return false; +#endif +} + + #if defined(SPLIT_KEYBOARD) && defined(SPLIT_DETECTED_OS_ENABLE) void slave_update_detected_host_os(os_variant_t os) { detected_os = os; diff --git a/quantum/os_detection.h b/quantum/os_detection.h index e9e7b25f1d27..fff3f867268c 100644 --- a/quantum/os_detection.h +++ b/quantum/os_detection.h @@ -49,3 +49,5 @@ void slave_update_detected_host_os(os_variant_t os); void print_stored_setups(void); void store_setups_in_eeprom(void); #endif + +bool os_detection_mcu_reset_is_pending(void); diff --git a/quantum/quantum.h b/quantum/quantum.h index 176c8a292d8f..93a1045c028f 100644 --- a/quantum/quantum.h +++ b/quantum/quantum.h @@ -274,6 +274,7 @@ void post_process_record_user(uint16_t keycode, keyrecord_t *record); void reset_keyboard(void); void soft_reset_keyboard(void); +void pre_mcu_reset_user(void); bool shutdown_kb(bool jump_to_bootloader); bool shutdown_user(bool jump_to_bootloader); diff --git a/quantum/split_common/split_util.c b/quantum/split_common/split_util.c index a35a16685a19..8e1cce876568 100644 --- a/quantum/split_common/split_util.c +++ b/quantum/split_common/split_util.c @@ -23,7 +23,6 @@ #include "wait.h" #include "debug.h" #include "usb_util.h" -#include "bootloader.h" #ifdef EE_HANDS # include "eeconfig.h" @@ -94,8 +93,9 @@ STATIC_ASSERT(SPLIT_USB_TIMEOUT < SPLIT_WATCHDOG_TIMEOUT, "SPLIT_WATCHDOG_TIMEOU # endif STATIC_ASSERT(SPLIT_MAX_CONNECTION_ERRORS > 0, "SPLIT_WATCHDOG_ENABLE requires SPLIT_MAX_CONNECTION_ERRORS be above 0 for a functioning disconnection check."); -static uint32_t split_watchdog_started = 0; -static bool split_watchdog_done = false; +static uint32_t split_watchdog_started = 0; +static bool split_watchdog_done = false; +static bool split_mcu_reset_pending = false; void split_watchdog_init(void) { split_watchdog_started = timer_read32(); @@ -115,10 +115,14 @@ bool split_watchdog_check(void) { void split_watchdog_task(void) { if (!split_watchdog_done && !is_keyboard_master()) { if (timer_elapsed32(split_watchdog_started) > SPLIT_WATCHDOG_TIMEOUT) { - mcu_reset(); + split_mcu_reset_pending = true; } } } + +bool split_mcu_reset_is_pending(void) { + return split_mcu_reset_pending; +} #endif // defined(SPLIT_WATCHDOG_ENABLE) #ifdef SPLIT_HAND_MATRIX_GRID diff --git a/quantum/split_common/split_util.h b/quantum/split_common/split_util.h index 6f4c4dc66027..33e56479e9ee 100644 --- a/quantum/split_common/split_util.h +++ b/quantum/split_common/split_util.h @@ -16,3 +16,4 @@ bool is_transport_connected(void); void split_watchdog_update(bool done); void split_watchdog_task(void); bool split_watchdog_check(void); +bool split_mcu_reset_is_pending(void);