/** * * @brief Dump thread information * * See _FaultDump() for example. * * @return N/A */ static void _FaultThreadShow(const NANO_ESF *esf) { PR_EXC(" Executing thread ID (thread): 0x%x\n" " Faulting instruction address: 0x%x\n", sys_thread_self_get(), esf->pc); }
int nanoCtxTaskTest(void) { nano_thread_id_t self_thread_id; TC_PRINT("Testing sys_thread_self_get() from an ISR and task\n"); self_thread_id = sys_thread_self_get(); isrInfo.command = THREAD_SELF_CMD; isrInfo.error = 0; _trigger_isrHandler(); if ((isrInfo.error != 0) || (isrInfo.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 sys_execution_context_type_get() from an ISR\n"); isrInfo.command = EXEC_CTX_TYPE_CMD; isrInfo.error = 0; _trigger_isrHandler(); if ((isrInfo.error != 0) || (isrInfo.value != NANO_CTX_ISR)) { return TC_FAIL; } TC_PRINT("Testing sys_execution_context_type_get() from a task\n"); if (sys_execution_context_type_get() != NANO_CTX_TASK) { return TC_FAIL; } return TC_PASS; }
/** * * @brief Nanokernel fatal error handler * * This routine is called when a fatal error condition is detected by either * hardware or software. * * The caller is expected to always provide a usable ESF. In the event that the * fatal error does not have a hardware generated ESF, the caller should either * create its own or use a pointer to the global default ESF <_default_esf>. * * @param reason the reason that the handler was called * @param pEsf pointer to the exception stack frame * * @return This function does not return. */ FUNC_NORETURN void _NanoFatalErrorHandler(unsigned int reason, const NANO_ESF *pEsf) { _debug_fatal_hook(pEsf); #ifdef CONFIG_PRINTK /* Display diagnostic information about the error */ switch (reason) { case _NANO_ERR_CPU_EXCEPTION: break; case _NANO_ERR_SPURIOUS_INT: printk("***** Unhandled interrupt vector %d occurred! " "*****\n", _loapic_isr_vector_get()); break; case _NANO_ERR_INVALID_TASK_EXIT: printk("***** Invalid Exit Software Error! *****\n"); break; #if defined(CONFIG_STACK_CANARIES) case _NANO_ERR_STACK_CHK_FAIL: printk("***** Stack Check Fail! *****\n"); break; #endif /* CONFIG_STACK_CANARIES */ case _NANO_ERR_ALLOCATION_FAIL: printk("**** Kernel Allocation Failure! ****\n"); break; default: printk("**** Unknown Fatal Error %d! ****\n", reason); break; } printk("Current thread ID = 0x%x\n" "Faulting segment:address = 0x%x:0x%x\n" "eax: 0x%x, ebx: 0x%x, ecx: 0x%x, edx: 0x%x\n" "esi: 0x%x, edi: 0x%x, ebp: 0%x, esp: 0x%x\n" "eflags: 0x%x\n", sys_thread_self_get(), pEsf->cs & 0xFFFF, pEsf->eip, pEsf->eax, pEsf->ebx, pEsf->ecx, pEsf->edx, pEsf->esi, pEsf->edi, pEsf->ebp, pEsf->esp, pEsf->eflags); #endif /* CONFIG_PRINTK */ /* * Error was fatal to a kernel task or a fiber; invoke the system * fatal error handling policy defined for the platform. */ _SysFatalErrorHandler(reason, pEsf); }
void isr_handler(void *data) { ARG_UNUSED(data); switch (isrInfo.command) { case THREAD_SELF_CMD: isrInfo.data = (void *) sys_thread_self_get(); break; case EXEC_CTX_TYPE_CMD: isrInfo.value = sys_execution_context_type_get(); break; default: isrInfo.error = UNKNOWN_COMMAND; break; } }
int sol_mainloop_impl_platform_init(void) { int i; main_thread_id = sys_thread_self_get(); nano_sem_init(&_sol_mainloop_lock); nano_sem_give(&_sol_mainloop_lock); nano_fifo_init(&_sol_mainloop_pending_events); nano_fifo_init(&_sol_mainloop_free_events); for (i = 0; i < sol_util_array_size(_events); i++) { struct me_fifo_entry *mfe; mfe = &_events[i]; nano_fifo_put(&_sol_mainloop_free_events, mfe); } return 0; }
static void fiberHelper(int arg1, int arg2) { nano_thread_id_t self_thread_id; ARG_UNUSED(arg1); ARG_UNUSED(arg2); /* * This fiber starts off at a higher priority than fiberEntry(). Thus, it * should execute immediately. */ fiberEvidence++; /* Test that helper will yield to a fiber of equal priority */ self_thread_id = sys_thread_self_get(); self_thread_id->prio++; /* Lower priority to that of fiberEntry() */ fiber_yield(); /* Yield to fiber of equal priority */ fiberEvidence++; /* <fiberEvidence> should now be 2 */ }
int nanoCtxFiberTest(nano_thread_id_t task_thread_id) { nano_thread_id_t self_thread_id; self_thread_id = sys_thread_self_get(); if (self_thread_id == task_thread_id) { fiberDetectedError = 1; return TC_FAIL; } isrInfo.command = THREAD_SELF_CMD; isrInfo.error = 0; _trigger_isrHandler(); if ((isrInfo.error != 0) || (isrInfo.data != (void *) self_thread_id)) { /* * Either the ISR detected an error, or the ISR context ID does not * match the interrupted fiber's thread ID. */ fiberDetectedError = 2; return TC_FAIL; } isrInfo.command = EXEC_CTX_TYPE_CMD; isrInfo.error = 0; _trigger_isrHandler(); if ((isrInfo.error != 0) || (isrInfo.value != NANO_CTX_ISR)) { fiberDetectedError = 3; return TC_FAIL; } if (sys_execution_context_type_get() != NANO_CTX_FIBER) { fiberDetectedError = 4; return TC_FAIL; } return TC_PASS; }
/** * * @brief Dump information regarding fault (FAULT_DUMP == 1) * * Dump information regarding the fault when CONFIG_FAULT_DUMP is set to 1 * (short form). * * eg. (precise bus error escalated to hard fault): * * Fault! EXC #3, Thread: 0x200000dc, instr: 0x000011d3 * HARD FAULT: Escalation (see below)! * MMFSR: 0x00000000, BFSR: 0x00000082, UFSR: 0x00000000 * BFAR: 0xff001234 * * @return N/A */ void _FaultDump(const NANO_ESF *esf, int fault) { int escalation = 0; PR_EXC("Fault! EXC #%d, Thread: %x, instr @ %x\n", fault, sys_thread_self_get(), esf->pc); if (3 == fault) { /* hard fault */ escalation = _ScbHardFaultIsForced(); PR_EXC("HARD FAULT: %s\n", escalation ? "Escalation (see below)!" : "Bus fault on vector table read\n"); } PR_EXC("MMFSR: %x, BFSR: %x, UFSR: %x\n", __scs.scb.cfsr.byte.mmfsr.val, __scs.scb.cfsr.byte.bfsr.val, __scs.scb.cfsr.byte.ufsr.val); if (_ScbMemFaultIsMmfarValid()) { PR_EXC("MMFAR: %x\n", _ScbMemFaultAddrGet()); if (escalation) { _ScbMemFaultMmfarReset(); } } if (_ScbBusFaultIsBfarValid()) { PR_EXC("BFAR: %x\n", _ScbBusFaultAddrGet()); if (escalation) { _ScbBusFaultBfarReset(); } } /* clear USFR sticky bits */ _ScbUsageFaultAllFaultsReset(); }
void main(void) { int rv; /* return value from tests */ TC_START("Test Nanokernel CPU and thread routines"); TC_PRINT("Initializing nanokernel objects\n"); rv = initNanoObjects(); if (rv != TC_PASS) { goto doneTests; } TC_PRINT("Testing nano_cpu_idle()\n"); rv = nano_cpu_idleTest(); if (rv != TC_PASS) { goto doneTests; } TC_PRINT("Testing interrupt locking and unlocking\n"); rv = nanoCpuDisableInterruptsTest(irq_lockWrapper, irq_unlockWrapper, -1); if (rv != TC_PASS) { goto doneTests; } /* * The Cortex-M3/M4 use the SYSTICK exception for the system timer, which is * not considered an IRQ by the irq_enable/Disable APIs. */ #if !defined(CONFIG_CPU_CORTEX_M3_M4) /* Disable interrupts coming from the timer. */ TC_PRINT("Testing irq_disable() and irq_enable()\n"); rv = nanoCpuDisableInterruptsTest(irq_disableWrapper, irq_enableWrapper, TICK_IRQ); if (rv != TC_PASS) { goto doneTests; } #endif rv = nanoCtxTaskTest(); if (rv != TC_PASS) { goto doneTests; } TC_PRINT("Spawning a fiber from a task\n"); fiberEvidence = 0; task_fiber_start(fiberStack1, FIBER_STACKSIZE, fiberEntry, (int) sys_thread_self_get(), 0, FIBER_PRIORITY, 0); if (fiberEvidence != 1) { rv = TC_FAIL; TC_ERROR(" - fiber did not execute as expected!\n"); goto doneTests; } /* * The fiber ran, now wake it so it can test sys_thread_self_get and * sys_execution_context_type_get. */ TC_PRINT("Fiber to test sys_thread_self_get() and sys_execution_context_type_get\n"); nano_task_sem_give(&wakeFiber); if (fiberDetectedError != 0) { rv = TC_FAIL; TC_ERROR(" - failure detected in fiber; fiberDetectedError = %d\n", fiberDetectedError); goto doneTests; } TC_PRINT("Fiber to test fiber_yield()\n"); nano_task_sem_give(&wakeFiber); if (fiberDetectedError != 0) { rv = TC_FAIL; TC_ERROR(" - failure detected in fiber; fiberDetectedError = %d\n", fiberDetectedError); goto doneTests; } nano_task_sem_give(&wakeFiber); rv = test_timeout(); if (rv != TC_PASS) { goto doneTests; } /* Cortex-M3/M4 does not implement connecting non-IRQ exception handlers */ #if !defined(CONFIG_CPU_CORTEX_M3_M4) /* * Test divide by zero exception handler. * * WARNING: This code has been very carefully crafted so that it does * what it is supposed to. Both "error" and "excHandlerExecuted" must be * volatile to prevent the compiler from issuing a "divide by zero" * warning (since otherwise in knows "excHandlerExecuted" is zero), * and to ensure the compiler issues the two byte "idiv" instruction * that the exception handler is designed to deal with. */ volatile int error; /* used to create a divide by zero error */ TC_PRINT("Verifying exception handler installed\n"); excHandlerExecuted = 0; error = error / excHandlerExecuted; TC_PRINT("excHandlerExecuted: %d\n", excHandlerExecuted); rv = (excHandlerExecuted == 1) ? TC_PASS : TC_FAIL; #endif doneTests: TC_END_RESULT(rv); TC_END_REPORT(rv); }
int fiber_yieldTest(void) { nano_thread_id_t self_thread_id; /* * Start a fiber of higher priority. Note that since the new fiber is * being started from a fiber, it will not automatically switch to the * fiber as it would if done from a task. */ self_thread_id = sys_thread_self_get(); fiberEvidence = 0; fiber_fiber_start(fiberStack2, FIBER_STACKSIZE, fiberHelper, 0, 0, FIBER_PRIORITY - 1, 0); if (fiberEvidence != 0) { /* ERROR! Helper spawned at higher */ fiberDetectedError = 10; /* priority ran prematurely. */ return TC_FAIL; } /* * Test that the fiber will yield to the higher priority helper. * <fiberEvidence> is still 0. */ fiber_yield(); if (fiberEvidence == 0) { /* ERROR! Did not yield to higher */ fiberDetectedError = 11; /* priority fiber. */ return TC_FAIL; } if (fiberEvidence > 1) { /* ERROR! Helper did not yield to */ fiberDetectedError = 12; /* equal priority fiber. */ return TC_FAIL; } /* * Raise the priority of fiberEntry(). Calling fiber_yield() should * not result in switching to the helper. */ self_thread_id->prio--; fiber_yield(); if (fiberEvidence != 1) { /* ERROR! Context switched to a lower */ fiberDetectedError = 13; /* priority fiber! */ return TC_FAIL; } /* * Block on <wakeFiber>. This will allow the helper fiber to complete. * The main task will wake this fiber. */ nano_fiber_sem_take(&wakeFiber, TICKS_UNLIMITED); return TC_PASS; }
bool sol_mainloop_impl_main_thread_check(void) { return main_thread_id == sys_thread_self_get(); }