/** * Function is implemented as weak so that it can be overwritten by custom application error handler * when needed. */ __WEAK void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info) { __disable_irq(); NRF_LOG_FINAL_FLUSH(); #ifndef DEBUG NRF_LOG_ERROR("Fatal error"); #else switch (id) { #if defined(SOFTDEVICE_PRESENT) && SOFTDEVICE_PRESENT case NRF_FAULT_ID_SD_ASSERT: NRF_LOG_ERROR("SOFTDEVICE: ASSERTION FAILED"); break; case NRF_FAULT_ID_APP_MEMACC: NRF_LOG_ERROR("SOFTDEVICE: INVALID MEMORY ACCESS"); break; #endif case NRF_FAULT_ID_SDK_ASSERT: { assert_info_t * p_info = (assert_info_t *)info; NRF_LOG_ERROR("ASSERTION FAILED at %s:%u", p_info->p_file_name, p_info->line_num); break; } case NRF_FAULT_ID_SDK_ERROR: { error_info_t * p_info = (error_info_t *)info; NRF_LOG_ERROR("ERROR %u [%s] at %s:%u\r\nPC at: 0x%08x", p_info->err_code, nrf_strerror_get(p_info->err_code), p_info->p_file_name, p_info->line_num, pc); NRF_LOG_ERROR("End of error report"); break; } default: NRF_LOG_ERROR("UNKNOWN FAULT at 0x%08X", pc); break; } #endif NRF_BREAKPOINT_COND; // On assert, the system can only recover with a reset. #ifndef DEBUG NRF_LOG_WARNING("System reset"); NVIC_SystemReset(); #else app_error_save_and_stop(id, pc, info); #endif // DEBUG }
/** * Function is implemented as weak so that it can be overwritten by custom application error handler * when needed. */ __WEAK void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info) { static volatile struct { uint32_t fault_id; uint32_t pc; uint32_t error_info; assert_info_t * p_assert_info; error_info_t * p_error_info; ret_code_t err_code; uint32_t line_num; const uint8_t * p_file_name; } m_error_data = {0}; // The following variable helps Keil keep the call stack visible, in addition, it can be set to // 0 in the debugger to continue executing code after the error check. volatile bool loop = true; UNUSED_VARIABLE(loop); m_error_data.fault_id = id; m_error_data.pc = pc; m_error_data.error_info = info; switch (id) { case NRF_FAULT_ID_SDK_ASSERT: m_error_data.p_assert_info = (assert_info_t *)info; m_error_data.line_num = m_error_data.p_assert_info->line_num; m_error_data.p_file_name = m_error_data.p_assert_info->p_file_name; rt_kprintf("app Assert fault handler:Line(%d)-File(%s)\n", m_error_data.line_num, m_error_data.p_file_name); break; case NRF_FAULT_ID_SDK_ERROR: m_error_data.p_error_info = (error_info_t *)info; m_error_data.err_code = m_error_data.p_error_info->err_code; m_error_data.line_num = m_error_data.p_error_info->line_num; m_error_data.p_file_name = m_error_data.p_error_info->p_file_name; rt_kprintf("app error fault handler:Line(%d)-File(%s)\n", m_error_data.line_num, m_error_data.p_file_name); break; } NRF_LOG_ERROR("Fatal\r\n"); NRF_LOG_FINAL_FLUSH(); // On assert, the system can only recover with a reset. #ifndef DEBUG NRF_LOG_INFO("Hit weak handler\r\n"); NVIC_SystemReset(); #else app_error_save_and_stop(id, pc, info); #endif // DEBUG }
/*lint -save -e14 */ void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info) { // disable INTs CRITICAL_REGION_ENTER(); NRF_LOG_ERROR("Fatal error"); NRF_LOG_FINAL_FLUSH(); #if LEDS_NUMBER > 0 /* Light a LED on error or warning. */ // nrf_gpio_cfg_output(SER_CONN_ASSERT_LED_PIN); // nrf_gpio_pin_set(SER_CONN_ASSERT_LED_PIN); #endif // m_p_error_file_name = p_file_name; // m_error_code = error_code; // m_error_line_num = line_num; /* Do not reset when warning. */ if (SER_WARNING_CODE != id) { /* This call can be used for debug purposes during application development. * @note CAUTION: Activating code below will write the stack to flash on an error. * This function should NOT be used in a final product. * It is intended STRICTLY for development/debugging purposes. * The flash write will happen EVEN if the radio is active, thus interrupting any communication. * Use with care. Un-comment the line below to use. */ /* ble_debug_assert_handler(error_code, line_num, p_file_name); */ #ifndef DEBUG /* Reset the chip. Should be used in the release version. */ NVIC_SystemReset(); #else /* Debug version. */ /* To be able to see function parameters in a debugger. */ uint32_t temp = 1; while (temp); #endif } CRITICAL_REGION_EXIT(); }
/**@brief Function runs the shutdown procedure. */ static void shutdown_process(void) { NRF_LOG_INFO("Shutdown started. Type %d\r\n", m_pwr_mgmt_evt); // Executing all callbacks. while (m_next_handler < PWR_MGMT_SECTION_VARS_COUNT) { if ((*PWR_MGMT_SECTION_VARS_GET(m_next_handler))(m_pwr_mgmt_evt)) { NRF_LOG_INFO("SysOff handler 0x%08X => ready\r\n", (unsigned int)*PWR_MGMT_SECTION_VARS_GET(m_next_handler)); } else { // One of the modules is not ready. NRF_LOG_INFO("SysOff handler 0x%08X => blocking\r\n", (unsigned int)*PWR_MGMT_SECTION_VARS_GET(m_next_handler)); return; } // Mark handler as executed. m_next_handler++; } #if NRF_PWR_MGMT_CONFIG_CPU_USAGE_MONITOR_ENABLED NRF_LOG_INFO("Maximum CPU usage: %u%%\r\n", m_max_cpu_usage); #endif // NRF_PWR_MGMT_CONFIG_CPU_USAGE_MONITOR_ENABLED NRF_LOG_WARNING("Shutdown\r\n"); NRF_LOG_FINAL_FLUSH(); // Enter System OFF. #ifdef SOFTDEVICE_PRESENT ret_code_t ret_code = sd_power_system_off(); if (ret_code == NRF_ERROR_SOFTDEVICE_NOT_ENABLED) { NRF_POWER->SYSTEMOFF = POWER_SYSTEMOFF_SYSTEMOFF_Enter; } else { APP_ERROR_CHECK(ret_code); } #else NRF_POWER->SYSTEMOFF = POWER_SYSTEMOFF_SYSTEMOFF_Enter; #endif // SOFTDEVICE_PRESENT }
void HardFault_c_handler(uint32_t * p_stack_address) { #if defined(DEBUG_NRF) HardFault_p_stack = (HardFault_stack_t *)p_stack_address; (void)HardFault_p_stack; // Debugger detection is only possible on NRF52 (Cortex-M4), on NRF51 // (Cortex-M0) the processor has no access to CoreDebug registers. #if __CORTEX_M == 0x04 // C_DEBUGEN == 1 -> Debugger Connected if (CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk) { /* Generate breakpoint if debugger is connected */ NRF_BREAKPOINT; } #endif // __CORTEX_M == 0x04 #endif // DEBUG_NRF NRF_LOG_ERROR("Hardfault PC:%x\r\n", ((HardFault_stack_t *)p_stack_address)->pc); NRF_LOG_FINAL_FLUSH(); HardFault_process((HardFault_stack_t *)p_stack_address); }