[Core] Use a mutex guard for split shared memory (#16647)

This commit is contained in:
Stefan Kerkmann 2022-04-19 12:56:16 +02:00 committed by GitHub
parent 176ab14649
commit 7712a286dc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 82 additions and 20 deletions

View File

@ -5,6 +5,7 @@
#include "quantum.h" #include "quantum.h"
#include "serial.h" #include "serial.h"
#include "wait.h" #include "wait.h"
#include "synchronization_util.h"
#include <hal.h> #include <hal.h>
@ -86,7 +87,10 @@ static THD_FUNCTION(Thread1, arg) {
chRegSetThreadName("blinker"); chRegSetThreadName("blinker");
while (true) { while (true) {
palWaitLineTimeout(SOFT_SERIAL_PIN, TIME_INFINITE); palWaitLineTimeout(SOFT_SERIAL_PIN, TIME_INFINITE);
split_shared_memory_lock();
interrupt_handler(NULL); interrupt_handler(NULL);
split_shared_memory_unlock();
} }
} }
@ -205,14 +209,9 @@ void interrupt_handler(void *arg) {
chSysUnlockFromISR(); chSysUnlockFromISR();
} }
///////// static inline bool initiate_transaction(uint8_t sstd_index) {
// start transaction by initiator
//
// bool soft_serial_transaction(int sstd_index)
//
// this code is very time dependent, so we need to disable interrupts
bool soft_serial_transaction(int sstd_index) {
if (sstd_index > NUM_TOTAL_TRANSACTIONS) return false; if (sstd_index > NUM_TOTAL_TRANSACTIONS) return false;
split_transaction_desc_t *trans = &split_transaction_table[sstd_index]; split_transaction_desc_t *trans = &split_transaction_table[sstd_index];
// TODO: remove extra delay between transactions // TODO: remove extra delay between transactions
@ -239,8 +238,7 @@ bool soft_serial_transaction(int sstd_index) {
return false; return false;
} }
// if the slave is present syncronize with it // if the slave is present synchronize with it
uint8_t checksum = 0; uint8_t checksum = 0;
// send data to the slave // send data to the slave
serial_write_byte(sstd_index); // first chunk is transaction id serial_write_byte(sstd_index); // first chunk is transaction id
@ -286,3 +284,16 @@ bool soft_serial_transaction(int sstd_index) {
chSysUnlock(); chSysUnlock();
return true; return true;
} }
/////////
// start transaction by initiator
//
// bool soft_serial_transaction(int sstd_index)
//
// this code is very time dependent, so we need to disable interrupts
bool soft_serial_transaction(int sstd_index) {
split_shared_memory_lock();
bool result = initiate_transaction((uint8_t)sstd_index);
split_shared_memory_unlock();
return result;
}

View File

@ -15,6 +15,7 @@
*/ */
#include "serial_usart.h" #include "serial_usart.h"
#include "synchronization_util.h"
#if defined(SERIAL_USART_CONFIG) #if defined(SERIAL_USART_CONFIG)
static SerialConfig serial_config = SERIAL_USART_CONFIG; static SerialConfig serial_config = SERIAL_USART_CONFIG;
@ -173,6 +174,7 @@ static THD_FUNCTION(SlaveThread, arg) {
* Parts of failed transactions or spurious bytes could still be in it. */ * Parts of failed transactions or spurious bytes could still be in it. */
usart_clear(); usart_clear();
} }
split_shared_memory_unlock();
} }
} }
@ -200,6 +202,7 @@ static inline bool react_to_transactions(void) {
return false; return false;
} }
split_shared_memory_lock();
split_transaction_desc_t* trans = &split_transaction_table[sstd_index]; split_transaction_desc_t* trans = &split_transaction_table[sstd_index];
/* Send back the handshake which is XORed as a simple checksum, /* Send back the handshake which is XORed as a simple checksum,
@ -254,7 +257,12 @@ bool soft_serial_transaction(int index) {
/* Clear the receive queue, to start with a clean slate. /* Clear the receive queue, to start with a clean slate.
* Parts of failed transactions or spurious bytes could still be in it. */ * Parts of failed transactions or spurious bytes could still be in it. */
usart_clear(); usart_clear();
return initiate_transaction((uint8_t)index);
split_shared_memory_lock();
bool result = initiate_transaction((uint8_t)index);
split_shared_memory_unlock();
return result;
} }
/** /**

View File

@ -265,7 +265,8 @@ PLATFORM_SRC = \
$(STREAMSSRC) \ $(STREAMSSRC) \
$(CHIBIOS)/os/various/syscalls.c \ $(CHIBIOS)/os/various/syscalls.c \
$(PLATFORM_COMMON_DIR)/syscall-fallbacks.c \ $(PLATFORM_COMMON_DIR)/syscall-fallbacks.c \
$(PLATFORM_COMMON_DIR)/wait.c $(PLATFORM_COMMON_DIR)/wait.c \
$(PLATFORM_COMMON_DIR)/synchronization_util.c
# Ensure the ASM files are not subjected to LTO -- it'll strip out interrupt handlers otherwise. # Ensure the ASM files are not subjected to LTO -- it'll strip out interrupt handlers otherwise.
QUANTUM_LIB_SRC += $(STARTUPASM) $(PORTASM) $(OSALASM) $(PLATFORMASM) QUANTUM_LIB_SRC += $(STARTUPASM) $(PORTASM) $(OSALASM) $(PLATFORMASM)
@ -420,6 +421,9 @@ LDFLAGS += $(SHARED_LDFLAGS) $(SHARED_LDSYMBOLS) $(TOOLCHAIN_LDFLAGS) $(TOOLCHA
# Tell QMK that we are hosting it on ChibiOS. # Tell QMK that we are hosting it on ChibiOS.
OPT_DEFS += -DPROTOCOL_CHIBIOS OPT_DEFS += -DPROTOCOL_CHIBIOS
# ChibiOS supports synchronization primitives like a Mutex
OPT_DEFS += -DPLATFORM_SUPPORTS_SYNCHRONIZATION
# Workaround to stop ChibiOS from complaining about new GCC -- it's been fixed for 7/8/9 already # Workaround to stop ChibiOS from complaining about new GCC -- it's been fixed for 7/8/9 already
OPT_DEFS += -DPORT_IGNORE_GCC_VERSION_CHECK=1 OPT_DEFS += -DPORT_IGNORE_GCC_VERSION_CHECK=1

View File

@ -0,0 +1,26 @@
// Copyright 2022 Stefan Kerkmann
// SPDX-License-Identifier: GPL-2.0-or-later
#include "synchronization_util.h"
#include "ch.h"
#if defined(SPLIT_KEYBOARD)
static MUTEX_DECL(SPLIT_SHARED_MEMORY_MUTEX);
/**
* @brief Acquire exclusive access to the split keyboard shared memory, by
* locking the mutex guarding it. If the mutex is already held, the calling
* thread will be suspended until the mutex currently owning thread releases the
* mutex again.
*/
void split_shared_memory_lock(void) {
chMtxLock(&SPLIT_SHARED_MEMORY_MUTEX);
}
/**
* @brief Release the split shared memory mutex that has been acquired before.
*/
void split_shared_memory_unlock(void) {
chMtxUnlock(&SPLIT_SHARED_MEMORY_MUTEX);
}
#endif

View File

@ -0,0 +1,14 @@
// Copyright 2022 Stefan Kerkmann
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#if defined(PLATFORM_SUPPORTS_SYNCHRONIZATION)
# if defined(SPLIT_KEYBOARD)
void split_shared_memory_lock(void);
void split_shared_memory_unlock(void);
# endif
#else
inline void split_shared_memory_lock(void){};
inline void split_shared_memory_unlock(void){};
#endif

View File

@ -23,8 +23,9 @@
#include "quantum.h" #include "quantum.h"
#include "transactions.h" #include "transactions.h"
#include "transport.h" #include "transport.h"
#include "split_util.h"
#include "transaction_id_define.h" #include "transaction_id_define.h"
#include "split_util.h"
#include "synchronization_util.h"
#define SYNC_TIMER_OFFSET 2 #define SYNC_TIMER_OFFSET 2
@ -63,9 +64,7 @@ static bool transaction_handler_master(matrix_row_t master_matrix[], matrix_row_
} }
} }
bool this_okay = true; bool this_okay = true;
ATOMIC_BLOCK_FORCEON { this_okay = handler(master_matrix, slave_matrix);
this_okay = handler(master_matrix, slave_matrix);
};
if (this_okay) return true; if (this_okay) return true;
} }
dprintf("Failed to execute %s\n", prefix); dprintf("Failed to execute %s\n", prefix);
@ -77,11 +76,11 @@ static bool transaction_handler_master(matrix_row_t master_matrix[], matrix_row_
if (!transaction_handler_master(master_matrix, slave_matrix, #prefix, &prefix##_handlers_master)) return false; \ if (!transaction_handler_master(master_matrix, slave_matrix, #prefix, &prefix##_handlers_master)) return false; \
} while (0) } while (0)
#define TRANSACTION_HANDLER_SLAVE(prefix) \ #define TRANSACTION_HANDLER_SLAVE(prefix) \
do { \ do { \
ATOMIC_BLOCK_FORCEON { \ split_shared_memory_lock(); \
prefix##_handlers_slave(master_matrix, slave_matrix); \ prefix##_handlers_slave(master_matrix, slave_matrix); \
}; \ split_shared_memory_unlock(); \
} while (0) } while (0)
inline static bool read_if_checksum_mismatch(int8_t trans_id_checksum, int8_t trans_id_retrieve, uint32_t *last_update, void *destination, const void *equiv_shmem, size_t length) { inline static bool read_if_checksum_mismatch(int8_t trans_id_checksum, int8_t trans_id_retrieve, uint32_t *last_update, void *destination, const void *equiv_shmem, size_t length) {