Skip to content
Closed
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
19 changes: 18 additions & 1 deletion platforms/chibios/bootloaders/kiibohd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}
14 changes: 14 additions & 0 deletions quantum/keyboard.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "eeconfig.h"
#include "action_layer.h"
#include "suspend.h"
#include "bootloader.h"

#ifdef BOOTMAGIC_ENABLE
# include "bootmagic.h"
#endif
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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();
Expand All @@ -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)
Expand Down Expand Up @@ -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();
}
}
20 changes: 12 additions & 8 deletions quantum/os_detection.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@

#include <string.h>
#include "timer.h"
#ifdef OS_DETECTION_KEYBOARD_RESET
# include "quantum.h"
#endif

#ifdef OS_DETECTION_DEBUG_ENABLE
# include "nvm_eeprom_eeconfig_internal.h"
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -206,13 +199,24 @@ 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;
}
#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;
Expand Down
2 changes: 2 additions & 0 deletions quantum/os_detection.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
1 change: 1 addition & 0 deletions quantum/quantum.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
12 changes: 8 additions & 4 deletions quantum/split_common/split_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
#include "wait.h"
#include "debug.h"
#include "usb_util.h"
#include "bootloader.h"

#ifdef EE_HANDS
# include "eeconfig.h"
Expand Down Expand Up @@ -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();
Expand All @@ -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
Expand Down
1 change: 1 addition & 0 deletions quantum/split_common/split_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);