void up_irqinitialize(void) { /* Currents_regs is non-NULL only while processing an interrupt */ CURRENT_REGS = NULL; /* The bulk of IRQ initialization if performed in str71x_head.S, so we * have very little to do here -- basically just enabling interrupts; * * Enable IRQs (but not FIQs -- they aren't used) */ putreg32(STR71X_EICICR_IRQEN, STR71X_EIC_ICR); /* This shouldn't be necessary, but it appears that something is needed * here to prevent spurious interrupts when the ARM interrupts are enabled * (Needs more investigation). */ up_mdelay(50); /* Wait a bit */ #if 0 putreg32(0, STR71X_EIC_IER); /* Make sure that all interrupts are disabled */ putreg32(0xffffffff, STR71X_EIC_IPR); /* And that no interrupts are pending */ #endif /* Initialize external interrupts */ str71x_xtiinitialize(); /* Enable global ARM interrupts */ #ifndef CONFIG_SUPPRESS_INTERRUPTS up_irq_restore(SVC_MODE | PSR_F_BIT); #endif }
void up_sigdeliver(void) { #ifndef CONFIG_DISABLE_SIGNALS struct tcb_s *rtcb = this_task(); uint32_t regs[XCPTCONTEXT_REGS]; sig_deliver_t sigdeliver; /* Save the errno. This must be preserved throughout the signal handling * so that the user code final gets the correct errno value (probably * EINTR). */ int saved_errno = rtcb->pterrno; board_autoled_on(LED_SIGNAL); sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n", rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); ASSERT(rtcb->xcp.sigdeliver != NULL); /* Save the real return state on the stack. */ up_copystate(regs, rtcb->xcp.regs); regs[REG_PC] = rtcb->xcp.saved_pc; regs[REG_SR] = rtcb->xcp.saved_sr; /* Get a local copy of the sigdeliver function pointer. We do this so * that we can nullify the sigdeliver function pointer in the TCB and * accept more signal deliveries while processing the current pending * signals. */ sigdeliver = rtcb->xcp.sigdeliver; rtcb->xcp.sigdeliver = NULL; /* Then restore the task interrupt state. */ up_irq_restore(regs[REG_SR] & 0x000000f0); /* Deliver the signals */ sigdeliver(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original * errno that is needed by the user logic (it is probably EINTR). */ sinfo("Resuming\n"); (void)up_irq_save(); rtcb->pterrno = saved_errno; /* Then restore the correct state for this thread of execution. */ board_autoled_off(LED_SIGNAL); up_fullcontextrestore(regs); #endif }
void up_irqinitialize(void) { int irq; /* Enable clock to interrupt controller */ lpc31_enableclock(CLKID_AHB2INTCCLK); /* AHB_TO_INTC_CLK */ lpc31_enableclock(CLKID_INTCCLK); /* INTC_CLK */ /* Set the vector base. We don't use direct vectoring, so these are set to 0. */ putreg32(0, LPC31_INTC_VECTOR0); putreg32(0, LPC31_INTC_VECTOR1); /* Set the priority treshold to 0, i.e. don't mask any interrupt on the * basis of priority level, for both targets (IRQ/FIQ) */ putreg32(0, LPC31_INTC_PRIORITYMASK0); /* Proc interrupt request 0: IRQ */ putreg32(0, LPC31_INTC_PRIORITYMASK1); /* Proc interrupt request 1: FIQ */ /* Disable all interrupts. Start from index 1 since 0 is unused. */ for (irq = 0; irq < NR_IRQS; irq++) { /* Initialize as high-active, disable the interrupt, set target to IRQ, * Set priority level to 1 (= lowest) for all the interrupt lines */ uint32_t address = LPC31_INTC_REQUEST(irq+1); putreg32(INTC_REQUEST_WEACTLOW | INTC_REQUEST_WEENABLE | INTC_REQUEST_TARGET_IRQ | INTC_REQUEST_PRIOLEVEL(1) | INTC_REQUEST_WEPRIO, address); } /* currents_regs is non-NULL only while processing an interrupt */ CURRENT_REGS = NULL; #ifndef CONFIG_SUPPRESS_INTERRUPTS /* And finally, enable interrupts */ up_irq_restore(SVC_MODE | PSR_F_BIT); #endif }
/* Restore the previous interrupt state which may still be interrupts * disabled (but we don't have a mechanism to verify that now) */ up_irq_restore(flags); } } #else /* defined(CONFIG_SCHED_INSTRUMENTATION_CSECTION) */ void leave_critical_section(irqstate_t flags) { /* Check if we were called from an interrupt handler */ if (!up_interrupt_context()) { FAR struct tcb_s *rtcb = this_task(); DEBUGASSERT(rtcb != NULL); /* Note that we have left the critical section */ sched_note_csection(rtcb, false); } /* Restore the previous interrupt state. */ up_irq_restore(flags); }
void up_irqinitialize(void) { /* currents_regs is non-NULL only while processing an interrupt */ g_current_regs = NULL; /* Initialize GPIO interrupt facilities */ #ifdef CONFIG_AVR32_GPIOIRQ #ifdef CONFIG_HAVE_WEAKFUNCTIONS if (gpio_irqinitialize != NULL) #endif { gpio_irqinitialize(); } #endif /* And finally, enable interrupts */ #ifndef CONFIG_SUPPRESS_INTERRUPTS up_irq_restore(getsreg() | (1 << SREG_I)); #endif }
void leave_critical_section(irqstate_t flags) { /* Do nothing if called from an interrupt handler */ if (!up_interrupt_context()) { FAR struct tcb_s *rtcb = this_task(); DEBUGASSERT(rtcb != 0 && rtcb->irqcount > 0); /* Will we still have interrupts disabled after decrementing the * count? */ if (rtcb->irqcount > 1) { /* Yes... make sure that the spinlock is set */ DEBUGASSERT(g_cpu_irqlock == SP_LOCKED); rtcb->irqcount--; } else { #ifdef CONFIG_SCHED_INSTRUMENTATION_CSECTION /* No.. Note that we have entered the critical section */ sched_note_csection(rtcb, false); #endif /* Decrement our count on the lock. If all CPUs have released, * then unlock the spinlock. */ rtcb->irqcount = 0; spin_clrbit(&g_cpu_irqset, this_cpu(), &g_cpu_irqsetlock, &g_cpu_irqlock); /* Have all CPUs release the lock? */ if (!spin_islocked(&g_cpu_irqlock)) { /* Check if there are pending tasks and that pre-emption is * also enabled. */ if (g_pendingtasks.head != NULL && !spin_islocked(&g_cpu_schedlock)) { /* Release any ready-to-run tasks that have collected in * g_pendingtasks if the scheduler is not locked. * * NOTE: This operation has a very high likelihood of causing * this task to be switched out! */ up_release_pending(); } } } /* Restore the previous interrupt state which may still be interrupts * disabled (but we don't have a mechanism to verify that now) */ up_irq_restore(flags); } }
void up_sigdeliver(void) { struct tcb_s *rtcb = this_task(); #if 0 uint32_t regs[XCPTCONTEXT_REGS+3]; /* Why +3? See below */ #else uint32_t regs[XCPTCONTEXT_REGS]; #endif sig_deliver_t sigdeliver; /* Save the errno. This must be preserved throughout the signal handling * so that the user code final gets the correct errno value (probably EINTR). */ int saved_errno = rtcb->pterrno; board_autoled_on(LED_SIGNAL); sdbg("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n", rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); ASSERT(rtcb->xcp.sigdeliver != NULL); /* Save the real return state on the stack. */ up_copystate(regs, rtcb->xcp.regs); regs[REG_PC] = rtcb->xcp.saved_pc; regs[REG_SR] = rtcb->xcp.saved_sr; /* Get a local copy of the sigdeliver function pointer. We do this so that * we can nullify the sigdeliver function pointer in the TCB and accept * more signal deliveries while processing the current pending signals. */ sigdeliver = rtcb->xcp.sigdeliver; rtcb->xcp.sigdeliver = NULL; /* Then restore the task interrupt state */ up_irq_restore(regs[REG_SR]); /* Deliver the signals */ sigdeliver(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original * errno that is needed by the user logic (it is probably EINTR). */ sdbg("Resuming\n"); (void)up_irq_save(); rtcb->pterrno = saved_errno; /* Then restore the correct state for this thread of execution. This is an * unusual case that must be handled by up_fullcontextresore. This case is * unusal in two ways: * * 1. It is not a context switch between threads. Rather, up_fullcontextrestore * must behave more it more like a longjmp within the same task, using * he same stack. * 2. In this case, up_fullcontextrestore is called with r12 pointing to * a register save area on the stack to be destroyed. This is * dangerous because there is the very real possibility that the new * stack pointer might overlap with the register save area and hat stack * usage in up_fullcontextrestore might corrupt the register save data * before the state is restored. At present, there does not appear to * be any stack overlap problems. If there were, then adding 3 words * to the size of register save structure size will protect its contents. */ board_autoled_off(LED_SIGNAL); up_fullcontextrestore(regs); }
void up_sigdeliver(void) { struct tcb_s *rtcb = this_task(); uint32_t regs[XCPTCONTEXT_REGS]; sig_deliver_t sigdeliver; /* Save the errno. This must be preserved throughout the signal handling * so that the user code final gets the correct errno value (probably * EINTR). */ int saved_errno = rtcb->pterrno; board_autoled_on(LED_SIGNAL); sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n", rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); ASSERT(rtcb->xcp.sigdeliver != NULL); /* Save the real return state on the stack. */ up_copystate(regs, rtcb->xcp.regs); regs[REG_EPC] = rtcb->xcp.saved_epc; regs[REG_STATUS] = rtcb->xcp.saved_status; /* Get a local copy of the sigdeliver function pointer. We do this so that * we can nullify the sigdeliver function pointer in the TCB and accept * more signal deliveries while processing the current pending signals. */ sigdeliver = rtcb->xcp.sigdeliver; rtcb->xcp.sigdeliver = NULL; /* Then restore the task interrupt state */ up_irq_restore((irqstate_t)regs[REG_STATUS]); /* Deliver the signals */ sigdeliver(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original * errno that is needed by the user logic (it is probably EINTR). */ sinfo("Resuming EPC: %08x STATUS: %08x\n", regs[REG_EPC], regs[REG_STATUS]); (void)up_irq_save(); rtcb->pterrno = saved_errno; /* Then restore the correct state for this thread of * execution. */ board_autoled_off(LED_SIGNAL); up_fullcontextrestore(regs); /* up_fullcontextrestore() should not return but could if the software * interrupts are disabled. */ PANIC(); }
void metal_irq_restore_enable(unsigned int flags) { up_irq_restore(flags); }