interrupt_handlers.c (1631B)
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 26 extern bool backing_store_allow_ecc_errors(void); 27 extern void backing_store_signal_ecc_error(void); 28 29 void 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 ///////////////////////////////////////////////////////////////////////////////