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

Implement split comms watchdog #18599

Merged
merged 5 commits into from
Oct 6, 2022
Merged
Show file tree
Hide file tree
Changes from 3 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
2 changes: 2 additions & 0 deletions data/mappings/info_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@
"SPLIT_USB_DETECT": {"info_key": "split.usb_detect.enabled", "value_type": "bool"},
"SPLIT_USB_TIMEOUT": {"info_key": "split.usb_detect.timeout", "value_type": "int"},
"SPLIT_USB_TIMEOUT_POLL": {"info_key": "split.usb_detect.polling_interval", "value_type": "int"},
"SPLIT_WATCHDOG_ENABLE": {"info_key": "split.transport.watchdog", "value_type": "bool"},
"SPLIT_WATCHDOG_TIMEOUT": {"info_key": "split.transport.watchdog_timeout", "value_type": "int"},
"SOFT_SERIAL_PIN": {"info_key": "split.soft_serial_pin"},
"SOFT_SERIAL_SPEED": {"info_key": "split.soft_serial_speed"},
"TAP_CODE_DELAY": {"info_key": "qmk.tap_keycode_delay", "value_type": "int"},
Expand Down
7 changes: 7 additions & 0 deletions docs/config_options.md
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,13 @@ There are a few different ways to set handedness for split keyboards (listed in

* `#define SPLIT_USB_TIMEOUT_POLL 10`
* Poll frequency when detecting master/slave when using `SPLIT_USB_DETECT`

* `#define SPLIT_WATCHDOG_ENABLE`
* Reboot slave if no communication from master within timeout.
* Helps resolve issue where both sides detect as slave using `SPLIT_USB_DETECT`

* `#define SPLIT_WATCHDOG_TIMEOUT 3000`
* Maximum slave timeout when waiting for communication from master when using `SPLIT_WATCHDOG_ENABLE`

* `#define FORCED_SYNC_THROTTLE_MS 100`
* Deadline for synchronizing data from master to slave when using the QMK-provided split transport.
Expand Down
11 changes: 11 additions & 0 deletions docs/feature_split_keyboard.md
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,17 @@ This sets the maximum timeout when detecting master/slave when using `SPLIT_USB_
```
This sets the poll frequency when detecting master/slave when using `SPLIT_USB_DETECT`

```c
#define SPLIT_WATCHDOG_ENABLE
```

This will enable a software watchdog on any side delegated as slave and will reboot the keyboard if no successful communication occurs within `SPLIT_WATCHDOG_TIMEOUT`. This can be particularly helpful when `SPLIT_USB_DETECT` delegates both sides as slave in some circumstances.

```c
#define SPLIT_WATCHDOG_TIMEOUT 3000
```
This set the maximum slave timeout when waiting for communication from master when using `SPLIT_WATCHDOG_ENABLE`

## Hardware Considerations and Mods

Master/slave delegation is made either by detecting voltage on VBUS connection or waiting for USB communication (`SPLIT_USB_DETECT`). Pro Micro boards can use VBUS detection out of the box and be used with or without `SPLIT_USB_DETECT`.
Expand Down
4 changes: 4 additions & 0 deletions quantum/keyboard.c
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,10 @@ void keyboard_task(void) {

quantum_task();

#if defined(SPLIT_WATCHDOG_ENABLE)
split_watchdog_task();
#endif

#if defined(RGBLIGHT_ENABLE)
rgblight_task();
#endif
Expand Down
43 changes: 43 additions & 0 deletions quantum/split_common/split_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,46 @@ static inline bool usbIsActive(void) {
}
#endif

#if defined(SPLIT_WATCHDOG_ENABLE)
# if !defined(SPLIT_WATCHDOG_TIMEOUT)
# if defined(SPLIT_USB_TIMEOUT)
# define SPLIT_WATCHDOG_TIMEOUT (SPLIT_USB_TIMEOUT + 100)
# else
# define SPLIT_WATCHDOG_TIMEOUT 3000
# endif
# else
# if defined(SPLIT_USB_TIMEOUT)
_Static_assert(SPLIT_USB_TIMEOUT > SPLIT_WATCHDOG_TIMEOUT, "SPLIT_WATCHDOG_TIMEOUT should not be below SPLIT_USB_TIMEOUT.");
# endif
# endif

static uint32_t split_watchdog_started = 0;
static bool split_watchdog_done = false;

void split_watchdog_init(void) {
split_watchdog_started = timer_read32();
}

void split_watchdog_update(bool done) {
split_watchdog_done = done;
}

bool split_watchdog_check(void) {
if (!is_transport_connected()) {
daskygit marked this conversation as resolved.
Show resolved Hide resolved
split_watchdog_done = false;
}
return split_watchdog_done;
}

void split_watchdog_task(void) {
if (!split_watchdog_done && !is_keyboard_master()) {
if (timer_elapsed32(split_watchdog_started) > SPLIT_WATCHDOG_TIMEOUT) {
mcu_reset();
}
}
}
#endif // defined(SPLIT_WATCHDOG_ENABLE)

#ifdef SPLIT_HAND_MATRIX_GRID
void matrix_io_delay(void);

Expand Down Expand Up @@ -179,6 +219,9 @@ void split_pre_init(void) {
void split_post_init(void) {
if (!is_keyboard_master()) {
transport_slave_init();
#if defined(SPLIT_WATCHDOG_ENABLE)
split_watchdog_init();
#endif
}
}

Expand Down
4 changes: 4 additions & 0 deletions quantum/split_common/split_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,7 @@ void split_post_init(void);

bool transport_master_if_connected(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]);
bool is_transport_connected(void);

void split_watchdog_update(bool done);
void split_watchdog_task(void);
bool split_watchdog_check(void);
4 changes: 4 additions & 0 deletions quantum/split_common/transaction_id_define.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ enum serial_transaction_id {
PUT_POINTING_CPI,
#endif // defined(POINTING_DEVICE_ENABLE) && defined(SPLIT_POINTING_ENABLE)

#if defined(SPLIT_WATCHDOG_ENABLE)
PUT_WATCHDOG,
#endif // defined(SPLIT_WATCHDOG_ENABLE)

#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
PUT_RPC_INFO,
PUT_RPC_REQ_DATA,
Expand Down
33 changes: 33 additions & 0 deletions quantum/split_common/transactions.c
Original file line number Diff line number Diff line change
Expand Up @@ -718,6 +718,36 @@ static void pointing_handlers_slave(matrix_row_t master_matrix[], matrix_row_t s

#endif // defined(POINTING_DEVICE_ENABLE) && defined(SPLIT_POINTING_ENABLE)

////////////////////////////////////////////////////
// WATCHDOG

#if defined(SPLIT_WATCHDOG_ENABLE)

static bool watchdog_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
bool okay = true;
if (!split_watchdog_check()) {
okay = transport_write(PUT_WATCHDOG, &okay, sizeof(okay));
split_watchdog_update(okay);
}
return okay;
}

static void watchdog_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
split_watchdog_update(split_shmem->watchdog_pinged);
KarlK90 marked this conversation as resolved.
Show resolved Hide resolved
}

# define TRANSACTIONS_WATCHDOG_MASTER() TRANSACTION_HANDLER_MASTER(watchdog)
# define TRANSACTIONS_WATCHDOG_SLAVE() TRANSACTION_HANDLER_SLAVE_AUTOLOCK(watchdog)
# define TRANSACTIONS_WATCHDOG_REGISTRATIONS [PUT_WATCHDOG] = trans_initiator2target_initializer(watchdog_pinged),

#else // defined(SPLIT_WATCHDOG_ENABLE)

# define TRANSACTIONS_WATCHDOG_MASTER()
# define TRANSACTIONS_WATCHDOG_SLAVE()
# define TRANSACTIONS_WATCHDOG_REGISTRATIONS

#endif // defined(SPLIT_WATCHDOG_ENABLE)

////////////////////////////////////////////////////

split_transaction_desc_t split_transaction_table[NUM_TOTAL_TRANSACTIONS] = {
Expand All @@ -744,6 +774,7 @@ split_transaction_desc_t split_transaction_table[NUM_TOTAL_TRANSACTIONS] = {
TRANSACTIONS_OLED_REGISTRATIONS
TRANSACTIONS_ST7565_REGISTRATIONS
TRANSACTIONS_POINTING_REGISTRATIONS
TRANSACTIONS_WATCHDOG_REGISTRATIONS
// clang-format on

#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
Expand All @@ -770,6 +801,7 @@ bool transactions_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix
TRANSACTIONS_OLED_MASTER();
TRANSACTIONS_ST7565_MASTER();
TRANSACTIONS_POINTING_MASTER();
TRANSACTIONS_WATCHDOG_MASTER();
return true;
}

Expand All @@ -789,6 +821,7 @@ void transactions_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[
TRANSACTIONS_OLED_SLAVE();
TRANSACTIONS_ST7565_SLAVE();
TRANSACTIONS_POINTING_SLAVE();
TRANSACTIONS_WATCHDOG_SLAVE();
}

#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
Expand Down
4 changes: 4 additions & 0 deletions quantum/split_common/transport.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,10 @@ typedef struct _split_shared_memory_t {
split_slave_pointing_sync_t pointing;
#endif // defined(POINTING_DEVICE_ENABLE) && defined(SPLIT_POINTING_ENABLE)

#if defined(SPLIT_WATCHDOG_ENABLE)
bool watchdog_pinged;
#endif // defined(SPLIT_WATCHDOG_ENABLE)

#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
rpc_sync_info_t rpc_info;
uint8_t rpc_m2s_buffer[RPC_M2S_BUFFER_SIZE];
Expand Down