/** * * @brief Fatal error handler * * This routine implements the corrective action to be taken when the system * detects a fatal error. * * This sample implementation attempts to abort the current thread and allow * the system to continue executing, which may permit the system to continue * functioning with degraded capabilities. * * System designers may wish to enhance or substitute this sample * implementation to take other actions, such as logging error (or debug) * information to a persistent repository and/or rebooting the system. * * @param reason the fatal error reason * @param pEsf pointer to exception stack frame * * @return N/A */ __weak void _SysFatalErrorHandler(unsigned int reason, const NANO_ESF *pEsf) { ARG_UNUSED(pEsf); #if !defined(CONFIG_SIMPLE_FATAL_ERROR_HANDLER) #if defined(CONFIG_STACK_SENTINEL) if (reason == _NANO_ERR_STACK_CHK_FAIL) { goto hang_system; } #endif if (reason == _NANO_ERR_KERNEL_PANIC) { goto hang_system; } if (_is_thread_essential()) { printk("Fatal fault in essential thread! Spinning...\n"); goto hang_system; } printk("Fatal fault in thread %p! Aborting.\n", _current); k_thread_abort(_current); return; hang_system: #else ARG_UNUSED(reason); #endif for (;;) { k_cpu_idle(); } }
/* * Common thread entry point function (used by all threads) * * This routine invokes the actual thread entry point function and passes * it three arguments. It also handles graceful termination of the thread * if the entry point function ever returns. * * This routine does not return, and is marked as such so the compiler won't * generate preamble code that is only used by functions that actually return. */ FUNC_NORETURN void _thread_entry(void (*entry)(void *, void *, void *), void *p1, void *p2, void *p3) { entry(p1, p2, p3); #ifdef CONFIG_MULTITHREADING if (_is_thread_essential()) { _NanoFatalErrorHandler(_NANO_ERR_INVALID_TASK_EXIT, &_default_esf); } k_thread_abort(_current); #else for (;;) { k_cpu_idle(); } #endif /* * Compiler can't tell that k_thread_abort() won't return and issues a * warning unless we tell it that control never gets this far. */ CODE_UNREACHABLE; }
/** * * @brief Fatal error handler * * This routine implements the corrective action to be taken when the system * detects a fatal error. * * This sample implementation attempts to abort the current thread and allow * the system to continue executing, which may permit the system to continue * functioning with degraded capabilities. * * System designers may wish to enhance or substitute this sample * implementation to take other actions, such as logging error (or debug) * information to a persistent repository and/or rebooting the system. * * @param reason the fatal error reason * @param pEsf the pointer to the exception stack frame * * @return This function does not return. */ FUNC_NORETURN void _SysFatalErrorHandler(unsigned int reason, const NANO_ESF * pEsf) { nano_context_type_t curCtx = sys_execution_context_type_get(); ARG_UNUSED(reason); ARG_UNUSED(pEsf); if ((curCtx != NANO_CTX_ISR) && !_is_thread_essential(NULL)) { #ifdef CONFIG_MICROKERNEL if (curCtx == NANO_CTX_TASK) { extern FUNC_NORETURN void _TaskAbort(void); PRINTK("Fatal task error! Aborting task.\n"); _TaskAbort(); } else #endif /* CONFIG_MICROKERNEL */ { PRINTK("Fatal fiber error! Aborting fiber.\n"); fiber_abort(); } } else { #ifdef CONFIG_PRINTK /* * Conditionalize the ctxText[] definition to prevent an "unused * variable" warning when the PRINTK kconfig option is disabled. */ static const char * const ctxText[] = {"ISR", "essential fiber", "essential task"}; PRINTK("Fatal %s error! Spinning...\n", ctxText[curCtx]); #endif /* CONFIG_PRINTK */ } do { } while (1); }