Пример #1
0
/**
 *
 * @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);
}
Пример #2
0
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;
}
Пример #3
0
/**
 *
 * @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);
}
Пример #4
0
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;
	}
}
Пример #5
0
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;
}
Пример #6
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 */

}
Пример #7
0
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;
}
Пример #8
0
/**
 *
 * @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();
}
Пример #9
0
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);
}
Пример #10
0
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;
}
Пример #11
0
bool
sol_mainloop_impl_main_thread_check(void)
{
    return main_thread_id == sys_thread_self_get();
}