Parent directory

interrupt_handlers.c

1631 bytes
 1// Copyright 2023 Nick Brassel (@tzarc)
 2// SPDX-License-Identifier: GPL-2.0-or-later
 3
 4///////////////////////////////////////////////////////////////////////////////
 5// BEGIN: STM32 EFL Wear-leveling ECC fault handling
 6//
 7// Some STM32s have ECC checks for all flash memory access. Whenever there's an
 8// ECC failure, the MCU raises the NMI interrupt. Whenever we receive such an
 9// interrupt whilst reading the wear-leveling EEPROM area, we gracefully cater
10// for it, signalling the wear-leveling code that a failure has occurred.
11///////////////////////////////////////////////////////////////////////////////
12
13#include <ch.h>
14#include <chcore.h>
15
16#ifdef WEAR_LEVELING_EMBEDDED_FLASH
17#    ifdef QMK_MCU_SERIES_STM32L4XX
18#        define ECC_ERRORS_TRIGGER_NMI_INTERRUPT
19#        define ECC_CHECK_REGISTER FLASH->ECCR
20#        define ECC_CHECK_FLAG FLASH_ECCR_ECCD
21#    endif // QMK_MCU_SERIES_STM32L4XX
22#endif     // WEAR_LEVELING_EMBEDDED_FLASH
23
24#ifdef ECC_ERRORS_TRIGGER_NMI_INTERRUPT
25
26extern bool backing_store_allow_ecc_errors(void);
27extern void backing_store_signal_ecc_error(void);
28
29void NMI_Handler(void) {
30    if ((ECC_CHECK_REGISTER) & (ECC_CHECK_FLAG)) {
31        if (backing_store_allow_ecc_errors()) {
32            (ECC_CHECK_REGISTER) = (ECC_CHECK_FLAG);
33            backing_store_signal_ecc_error();
34            return;
35        }
36    }
37
38    chSysHalt("NMI");
39}
40
41#endif // ECC_ERRORS_TRIGGER_NMI_INTERRUPT
42
43///////////////////////////////////////////////////////////////////////////////
44// END: STM32 EFL Wear-leveling ECC fault handling
45///////////////////////////////////////////////////////////////////////////////