Exemplo n.º 1
0
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
}
Exemplo n.º 2
0
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
}
Exemplo n.º 3
0
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
}
Exemplo n.º 4
0
      /* 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);
}
Exemplo n.º 5
0
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
}
Exemplo n.º 6
0
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);
    }
}
Exemplo n.º 7
0
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);
}
Exemplo n.º 8
0
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();
}
Exemplo n.º 9
0
void metal_irq_restore_enable(unsigned int flags)
{
	up_irq_restore(flags);
}