/** * * @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 fatal error reason * @param pEsf pointer to exception stack frame * * @return This function does not return. */ void __weak z_SysFatalErrorHandler(unsigned int reason, const NANO_ESF *pEsf) { ARG_UNUSED(pEsf); #if !defined(CONFIG_SIMPLE_FATAL_ERROR_HANDLER) #ifdef CONFIG_STACK_SENTINEL if (reason == _NANO_ERR_STACK_CHK_FAIL) { goto hang_system; } #endif if (reason == _NANO_ERR_KERNEL_PANIC) { goto hang_system; } if (k_is_in_isr() || z_is_thread_essential()) { printk("Fatal fault in %s! Spinning...\n", k_is_in_isr() ? "ISR" : "essential thread"); 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(); } CODE_UNREACHABLE; }
int usb_dc_ep_write(const u8_t ep, const u8_t *const data, const u32_t data_len, u32_t * const ret_bytes) { struct usb_dc_stm32_ep_state *ep_state = usb_dc_stm32_get_ep_state(ep); HAL_StatusTypeDef status; u32_t len = data_len; int ret = 0; LOG_DBG("ep 0x%02x, len %u", ep, data_len); if (!ep_state || !EP_IS_IN(ep)) { LOG_ERR("invalid ep 0x%02x", ep); return -EINVAL; } ret = k_sem_take(&ep_state->write_sem, K_NO_WAIT); if (ret) { LOG_ERR("Unable to get write lock (%d)", ret); return -EAGAIN; } if (!k_is_in_isr()) { irq_disable(DT_USB_IRQ); } if (ep == EP0_IN && len > USB_MAX_CTRL_MPS) { len = USB_MAX_CTRL_MPS; } status = HAL_PCD_EP_Transmit(&usb_dc_stm32_state.pcd, ep, (void *)data, len); if (status != HAL_OK) { LOG_ERR("HAL_PCD_EP_Transmit failed(0x%02x), %d", ep, (int)status); k_sem_give(&ep_state->write_sem); ret = -EIO; } if (!ret && ep == EP0_IN && len > 0) { /* Wait for an empty package as from the host. * This also flushes the TX FIFO to the host. */ usb_dc_ep_start_read(ep, NULL, 0); } if (!k_is_in_isr()) { irq_enable(DT_USB_IRQ); } if (ret_bytes) { *ret_bytes = len; } return ret; }
/** * * @brief Test some context routines from a preemptible thread * * This routines tests the k_current_get() and * k_is_in_isr() routines from both a preemtible thread and an ISR (that * interrupted a preemtible thread). Checking those routines with cooperative * threads are done elsewhere. * * @return TC_PASS on success * @return TC_FAIL on failure */ static int test_kernel_ctx_task(void) { k_tid_t self_thread_id; TC_PRINT("Testing k_current_get() from an ISR and task\n"); self_thread_id = k_current_get(); isr_info.command = THREAD_SELF_CMD; isr_info.error = 0; /* isr_info is modified by the isr_handler routine */ isr_handler_trigger(); if (isr_info.error || isr_info.data != (void *)self_thread_id) { /* * Either the ISR detected an error, or the ISR context ID * does not match the interrupted task's thread ID. */ return TC_FAIL; } TC_PRINT("Testing k_is_in_isr() from an ISR\n"); isr_info.command = EXEC_CTX_TYPE_CMD; isr_info.error = 0; isr_handler_trigger(); if (isr_info.error || isr_info.value != K_ISR) { return TC_FAIL; } TC_PRINT("Testing k_is_in_isr() from a preemtible thread\n"); if (k_is_in_isr() || _current->base.prio < 0) { return TC_FAIL; } return TC_PASS; }
/** * * @brief Handler to perform various actions from within an ISR context * * This routine is the ISR handler for isr_handler_trigger(). It performs * the command requested in <isr_info.command>. * * @return N/A */ static void isr_handler(void *data) { ARG_UNUSED(data); switch (isr_info.command) { case THREAD_SELF_CMD: isr_info.data = (void *)k_current_get(); break; case EXEC_CTX_TYPE_CMD: if (k_is_in_isr()) { isr_info.value = K_ISR; break; } if (_current->base.prio < 0) { isr_info.value = K_COOP_THREAD; break; } isr_info.value = K_PREEMPT_THREAD; break; default: isr_info.error = UNKNOWN_COMMAND; break; } }
int sys_execution_context_type_get(void) { if (k_is_in_isr()) return NANO_CTX_ISR; if (_current->base.prio < 0) return NANO_CTX_FIBER; return NANO_CTX_TASK; }
/** * * @brief Test some context routines from a preemptible thread * * This routines tests the k_current_get() and * k_is_in_isr() routines from both a preemtible thread and an ISR (that * interrupted a preemtible thread). Checking those routines with cooperative * threads are done elsewhere. * * @return TC_PASS on success * @return TC_FAIL on failure */ static int test_kernel_ctx_task(void) { k_tid_t self_thread_id; TC_PRINT("Testing k_current_get() from an ISR and task\n"); self_thread_id = k_current_get(); isr_info.command = THREAD_SELF_CMD; isr_info.error = 0; /* isr_info is modified by the isr_handler routine */ isr_handler_trigger(); if (isr_info.error) { TC_ERROR("ISR detected an error\n"); return TC_FAIL; } if (isr_info.data != (void *)self_thread_id) { TC_ERROR("ISR context ID mismatch\n"); return TC_FAIL; } TC_PRINT("Testing k_is_in_isr() from an ISR\n"); isr_info.command = EXEC_CTX_TYPE_CMD; isr_info.error = 0; isr_handler_trigger(); if (isr_info.error) { TC_ERROR("ISR detected an error\n"); return TC_FAIL; } if (isr_info.value != K_ISR) { TC_ERROR("isr_info.value was not K_ISR\n"); return TC_FAIL; } TC_PRINT("Testing k_is_in_isr() from a preemptible thread\n"); if (k_is_in_isr()) { TC_ERROR("Should not be in ISR context\n"); return TC_FAIL; } if (_current->base.prio < 0) { TC_ERROR("Current thread should have preemptible priority\n"); return TC_FAIL; } return TC_PASS; }
/** * * @brief Test the various context/thread routines from a cooperative thread * * This routines tests the k_current_get and * k_is_in_isr() routines from both a thread and an ISR (that interrupted a * cooperative thread). Checking those routines with preemptible threads are * done elsewhere. * * This routine may set <thread_detected_error> to the following values: * 1 - if thread ID matches that of the task * 2 - if thread ID taken during ISR does not match that of the thread * 3 - k_is_in_isr() when called from an ISR is false * 4 - k_is_in_isr() when called from a thread is true * 5 - if thread is not a cooperative thread * * @return TC_PASS on success * @return TC_FAIL on failure */ static int test_kernel_thread(k_tid_t task_thread_id) { k_tid_t self_thread_id; self_thread_id = k_current_get(); if (self_thread_id == task_thread_id) { thread_detected_error = 1; return TC_FAIL; } isr_info.command = THREAD_SELF_CMD; isr_info.error = 0; isr_handler_trigger(); if (isr_info.error || isr_info.data != (void *)self_thread_id) { /* * Either the ISR detected an error, or the ISR context ID * does not match the interrupted thread's thread ID. */ thread_detected_error = 2; return TC_FAIL; } isr_info.command = EXEC_CTX_TYPE_CMD; isr_info.error = 0; isr_handler_trigger(); if (isr_info.error || (isr_info.value != K_ISR)) { thread_detected_error = 3; return TC_FAIL; } if (k_is_in_isr()) { thread_detected_error = 4; return TC_FAIL; } if (_current->base.prio >= 0) { thread_detected_error = 5; return TC_FAIL; } return TC_PASS; }