Пример #1
0
void up_decodeirq(uint32_t *regs)
{
#ifdef CONFIG_SUPPRESS_INTERRUPTS
  lowsyslog("Unexpected IRQ\n");
  current_regs = regs;
  PANIC();
#else
  int index;
  int irq;

  /* Read the IRQ vector status register.  Bits 3-10 provide the IRQ number
   * of the interrupt (the TABLE_ADDR was initialized to zero, so the
   * following masking should be unnecessary)
   */

  index = getreg32(LPC31_INTC_VECTOR0) & INTC_VECTOR_INDEX_MASK;
  if (index != 0)
    {
      /* Shift the index so that the range of IRQ numbers are in bits 0-7 (values
       * 1-127) and back off the IRQ number by 1 so that the numbering is zero-based
       */

      irq = (index >> INTC_VECTOR_INDEX_SHIFT) -1;

      /* Verify that the resulting IRQ number is valid */

      if ((unsigned)irq < NR_IRQS)
        {
          uint32_t* savestate;

          /* Mask and acknowledge the interrupt */

          up_maskack_irq(irq);

          /* Current regs non-zero indicates that we are processing an interrupt;
           * current_regs is also used to manage interrupt level context switches.
           */

          savestate    = (uint32_t*)current_regs;
          current_regs = regs;

          /* Deliver the IRQ */

          irq_dispatch(irq, regs);

          /* Restore the previous value of current_regs.  NULL would indicate that
           * we are no longer in an interrupt handler.  It will be non-NULL if we
           * are returning from a nested interrupt.
           */

          current_regs = savestate;

          /* Unmask the last interrupt (global interrupts are still
           * disabled).
           */

          up_enable_irq(irq);
        }
    }
Пример #2
0
void up_decodeirq(uint32_t *regs)
{
#ifdef CONFIG_SUPPRESS_INTERRUPTS
  board_led_on(LED_INIRQ);
  lowsyslog("Unexpected IRQ\n");
  current_regs = regs;
  PANIC();
#else
  unsigned int irq;

  /* Read the IRQ number from the IVR register (Could probably get the same
   * info from CIC register without the setup).
   */

  board_led_on(LED_INIRQ);
  irq = getreg32(STR71X_EIC_IVR);

  /* Verify that the resulting IRQ number is valid */

  if (irq < NR_IRQS)
    {
      uint32_t* savestate;

      /* Current regs non-zero indicates that we are processing an interrupt;
       * current_regs is also used to manage interrupt level context switches.
       */

      savestate     = (uint32_t*)current_regs;
      current_regs = regs;

      /* Mask and acknowledge the interrupt */

      up_maskack_irq(irq);

      /* Deliver the IRQ */

      irq_dispatch(irq, regs);

      /* Restore the previous value of current_regs.  NULL would indicate that
       * we are no longer in an interrupt handler.  It will be non-NULL if we
       * are returning from a nested interrupt.
       */

      current_regs = savestate;

      /* Unmask the last interrupt (global interrupts are still disabled) */

      up_enable_irq(irq);
    }
#if CONFIG_DEBUG
  else
    {
      PANIC(); /* Normally never happens */
    }
#endif
  board_led_off(LED_INIRQ);
#endif
}
Пример #3
0
void up_decodeirq(uint32_t* regs)
{
#ifdef CONFIG_SUPPRESS_INTERRUPTS
  lowsyslog("Unexpected IRQ\n");
  current_regs = regs;
  PANIC();
#else
  /* Decode the interrupt.  First, fetch the interrupt id register. */

  uint16_t irqentry = getreg16(DM320_INTC_IRQENTRY0);

  /* The irqentry value is an offset into a table.  Zero means no interrupt. */

  if (irqentry != 0)
    {
      /* If non-zero, then we can map the table offset into an IRQ number */

      int irq = (irqentry >> 2) - 1;

      /* Verify that the resulting IRQ number is valid */

      if ((unsigned)irq < NR_IRQS)
        {
          uint32_t *savestate;

          /* Mask and acknowledge the interrupt */

          up_maskack_irq(irq);

          /* Current regs non-zero indicates that we are processing an interrupt;
           * current_regs is also used to manage interrupt level context switches.
           */

          savestate    = (uint32_t*)current_regs;
          current_regs = regs;

          /* Deliver the IRQ */

          irq_dispatch(irq, regs);

          /* Restore the previous value of current_regs.  NULL would indicate that
           * we are no longer in an interrupt handler.  It will be non-NULL if we
           * are returning from a nested interrupt.
           */

          current_regs = savestate;

          /* Unmask the last interrupt (global interrupts are still
           * disabled).
           */

          up_enable_irq(irq);
        }
    }
Пример #4
0
uint32_t *up_doirq(int irq, uint32_t *regs)
{
    up_ledon(LED_INIRQ);
#ifdef CONFIG_SUPPRESS_INTERRUPTS
    PANIC(OSERR_ERREXCEPTION);
#else
    uint32_t *savestate;

    /* Nested interrupts are not supported in this implementation.  If you want
     * to implement nested interrupts, you would have to (1) change the way that
     * current_regs is handled and (2) the design associated with
     * CONFIG_ARCH_INTERRUPTSTACK.  The savestate variable will not work for
     * that purpose as implemented here because only the outermost nested
     * interrupt can result in a context switch (it can probably be deleted).
     */

    /* Current regs non-zero indicates that we are processing an interrupt;
     * current_regs is also used to manage interrupt level context switches.
     */

    savestate    = (uint32_t*)current_regs;
    current_regs = regs;

    /* Mask and acknowledge the interrupt */

    up_maskack_irq(irq);

    /* Deliver the IRQ */

    irq_dispatch(irq, regs);

    /* If a context switch occurred while processing the interrupt then
     * current_regs may have change value.  If we return any value different
     * from the input regs, then the lower level will know that a context
     * switch occurred during interrupt processing.
     */

    regs = (uint32_t*)current_regs;

    /* Restore the previous value of current_regs.  NULL would indicate that
     * we are no longer in an interrupt handler.  It will be non-NULL if we
     * are returning from a nested interrupt.
     */

    current_regs = savestate;

    /* Unmask the last interrupt (global interrupts are still disabled) */

    up_enable_irq(irq);
#endif
    up_ledoff(LED_INIRQ);
    return regs;
}
Пример #5
0
uint32_t *up_doirq(int irq, uint32_t* regs)
{
  up_ledon(LED_INIRQ);
#ifdef CONFIG_SUPPRESS_INTERRUPTS
  PANIC(OSERR_ERREXCEPTION);
#else
  if ((unsigned)irq < NR_IRQS)
    {
       uint32_t *savestate;

       /* Current regs non-zero indicates that we are processing
        * an interrupt; current_regs is also used to manage
        * interrupt level context switches.
        */

       savestate    = (uint32_t*)current_regs;
       current_regs = regs;

       /* Mask and acknowledge the interrupt (if supported by the chip) */

#ifndef CONFIG_ARCH_NOINTC
       up_maskack_irq(irq);
#endif

       /* Deliver the IRQ */

       irq_dispatch(irq, regs);

       /* Get the current value of regs... it may have changed because
        * of a context switch performed during interrupt processing.
        */

       regs = current_regs;

       /* Restore the previous value of current_regs.  NULL would indicate that
        * we are no longer in an interrupt handler.  It will be non-NULL if we
        * are returning from a nested interrupt.
        */

       current_regs = savestate;

       /* Unmask the last interrupt (global interrupts are still
        * disabled.
        */

#ifndef CONFIG_ARCH_NOINTC
       up_enable_irq(irq);
#endif
    }
  up_ledoff(LED_INIRQ);
#endif
  return regs;
}
Пример #6
0
void up_decodeirq(uint32_t *regs)
{
  vic_vector_t vector = (vic_vector_t) vic_getreg(VIC_ADDRESS_OFFSET);

  /* Mask and acknowledge the interrupt */

  up_maskack_irq(irq);

  /* Valid Interrupt */

  if (vector != NULL)
    (vector) (regs);
}
Пример #7
0
static void lpc23xx_decodeirq(uint32_t *regs)
#endif
{
#ifdef CONFIG_SUPPRESS_INTERRUPTS
  lib_lowprintf("Unexpected IRQ\n");
  current_regs = regs;
  PANIC(OSERR_ERREXCEPTION);
#else

  /* Check which IRQ fires */

  uint32_t irqbits = vic_getreg(VIC_IRQSTATUS_OFFSET) & 0xFFFFFFFF;
  unsigned int irq;

  for (irq = 0; irq < NR_IRQS; irq++)
    {
      if (irqbits & (uint32_t) (1 << irq))
        break;
    }

  /* Verify that the resulting IRQ number is valid */

  if (irq < NR_IRQS)            /* redundant check ?? */
    {
       uint32_t *savestate;

      /* Current regs non-zero indicates that we are processing an interrupt;
       * current_regs is also used to manage interrupt level context switches.
       */

      savestate    = (uint32_t*)current_regs;
      current_regs = regs;

      /* Mask and acknowledge the interrupt */

      up_maskack_irq(irq);

      /* Deliver the IRQ */

      irq_dispatch(irq, regs);

      /* Restore the previous value of current_regs.  NULL would indicate that
       * we are no longer in an interrupt handler.  It will be non-NULL if we
       * are returning from a nested interrupt.
       */

      current_regs = savestate;
    }

#endif
}
Пример #8
0
void up_decodeirq(uint32_t* regs)
{
#ifdef CONFIG_SUPPRESS_INTERRUPTS
  lowsyslog(LOG_ERR, "Unexpected IRQ\n");
  current_regs = regs;
  PANIC();
#else
  uint32_t regval;
  int irq;

  /* Current regs non-zero indicates that we are processing an interrupt;
   * current_regs is also used to manage interrupt level context switches.
   *
   * Nested interrupts are not supported.
   */

  DEBUGASSERT(current_regs == NULL);
  current_regs = regs;

  /* Loop while there are pending interrupts to be processed */

  do
    {
      /* Decode the interrupt.  First, fetch the NIVECSR register. */

      regval = getreg32(IMX_AITC_NIVECSR);

      /* The MS 16 bits of the NIVECSR register contains vector index for the
       * highest pending normal interrupt.
       */

      irq = regval >> AITC_NIVECSR_NIVECTOR_SHIFT;

      /* If irq < 64, then this is the IRQ.  If there is no pending interrupt,
       * then irq will be >= 64 (it will be 0xffff for illegal source).
       */

      if (irq < NR_IRQS)
        {
          /* Mask and acknowledge the interrupt */

          up_maskack_irq(irq);

          /* Deliver the IRQ */

          irq_dispatch(irq, regs);

#if defined(CONFIG_ARCH_FPU) || defined(CONFIG_ARCH_ADDRENV)
          /* Check for a context switch.  If a context switch occurred, then
           * current_regs will have a different value than it did on entry.
           * If an interrupt level context switch has occurred, then restore
           * the floating point state and the establish the correct address
           * environment before returning from the interrupt.
           */

          if (regs != current_regs)
            {
#ifdef CONFIG_ARCH_FPU
              /* Restore floating point registers */

              up_restorefpu((uint32_t*)current_regs);
#endif

#ifdef CONFIG_ARCH_ADDRENV
              /* Make sure that the address environment for the previously
               * running task is closed down gracefully (data caches dump,
               * MMU flushed) and set up the address environment for the new
               * thread at the head of the ready-to-run list.
               */

              (void)group_addrenv(NULL);
#endif
            }
#endif
          /* Unmask the last interrupt (global interrupts are still
           * disabled).
           */

          up_enable_irq(irq);
        }
    }
  while (irq < NR_IRQS);

  /* Set current_regs to NULL to indicate that we are no longer in
   * an interrupt handler.
   */

  current_regs = NULL;
#endif
}
Пример #9
0
void up_decodeirq(uint32_t* regs)
{
#ifdef CONFIG_SUPPRESS_INTERRUPTS
  lowsyslog("Unexpected IRQ\n");
  current_regs = regs;
  PANIC(OSERR_ERREXCEPTION);
#else
  uint32_t* savestate;
  uint32_t regval;
  int irq;

  /* Current regs non-zero indicates that we are processing an interrupt;
   * current_regs is also used to manage interrupt level context switches.
   */

  savestate    = (uint32_t*)current_regs;
  current_regs = regs;

  /* Loop while there are pending interrupts to be processed */

  do
    {
      /* Decode the interrupt.  First, fetch the NIVECSR register. */

      regval = getreg32(IMX_AITC_NIVECSR);

      /* The MS 16 bits of the NIVECSR register contains vector index for the
       * highest pending normal interrupt.
       */

      irq = regval >> AITC_NIVECSR_NIVECTOR_SHIFT;

      /* If irq < 64, then this is the IRQ.  If there is no pending interrupt,
       * then irq will be >= 64 (it will be 0xffff for illegal source).
       */

      if (irq < NR_IRQS)
        {
          /* Mask and acknowledge the interrupt */

          up_maskack_irq(irq);

          /* Deliver the IRQ */

          irq_dispatch(irq, regs);

          /* Unmask the last interrupt (global interrupts are still
           * disabled).
           */

          up_enable_irq(irq);
        }
    }
  while (irq < NR_IRQS);

  /* Restore the previous value of current_regs.  NULL would indicate that
   * we are no longer in an interrupt handler.  It will be non-NULL if we
   * are returning from a nested interrupt.
   */

  current_regs = savestate;
#endif
}
Пример #10
0
void up_decodeirq(uint32_t* regs)
{
#ifdef CONFIG_SUPPRESS_INTERRUPTS
  lowsyslog("Unexpected IRQ\n");
  current_regs = regs;
  PANIC();
#else
  /* Decode the interrupt.  First, fetch the interrupt id register. */

  uint16_t irqentry = getreg16(DM320_INTC_IRQENTRY0);

  /* The irqentry value is an offset into a table.  Zero means no interrupt. */

  if (irqentry != 0)
    {
      /* If non-zero, then we can map the table offset into an IRQ number */

      int irq = (irqentry >> 2) - 1;

      /* Verify that the resulting IRQ number is valid */

      if ((unsigned)irq < NR_IRQS)
        {
          /* Mask and acknowledge the interrupt */

          up_maskack_irq(irq);

          /* Current regs non-zero indicates that we are processing an interrupt;
           * current_regs is also used to manage interrupt level context switches.
           *
           * Nested interrupts are not supported.
           */

          DEBUGASSERT(current_regs == NULL);
          current_regs = regs;

          /* Deliver the IRQ */

          irq_dispatch(irq, regs);

#if defined(CONFIG_ARCH_FPU) || defined(CONFIG_ARCH_ADDRENV)
          /* Check for a context switch.  If a context switch occurred, then
           * current_regs will have a different value than it did on entry.
           * If an interrupt level context switch has occurred, then restore
           * the floating point state and the establish the correct address
           * environment before returning from the interrupt.
           */

          if (regs != current_regs)
            {
#ifdef CONFIG_ARCH_FPU
              /* Restore floating point registers */

              up_restorefpu((uint32_t*)current_regs);
#endif

#ifdef CONFIG_ARCH_ADDRENV
              /* Make sure that the address environment for the previously
               * running task is closed down gracefully (data caches dump,
               * MMU flushed) and set up the address environment for the new
               * thread at the head of the ready-to-run list.
               */

              (void)group_addrenv(NULL);
#endif
            }
#endif

          /* Set current_regs to NULL to indicate that we are no longer in
           * an interrupt handler.
           */

          current_regs = NULL;

          /* Unmask the last interrupt (global interrupts are still
           * disabled).
           */

          up_enable_irq(irq);
        }
    }
Пример #11
0
uint32_t *up_doirq(int irq, uint32_t* regs)
{
  up_ledon(LED_INIRQ);
#ifdef CONFIG_SUPPRESS_INTERRUPTS
  PANIC();
#else
  if ((unsigned)irq < NR_IRQS)
    {
       uint32_t *savestate;

       /* Nested interrupts are not supported in this implementation.  If
        * you want to implement nested interrupts, you would have to (1)
        * change the way that current_regs is handled and (2) the design
        * associated with CONFIG_ARCH_INTERRUPTSTACK.  The savestate
        * variable will not work for that purpose as implemented here
        * because only the outermost nested interrupt can result in a
        * context switch (it can probably be deleted).
        */

       /* Current regs non-zero indicates that we are processing
        * an interrupt; current_regs is also used to manage
        * interrupt level context switches.
        */

       savestate    = (uint32_t*)current_regs;
       current_regs = regs;

       /* Mask and acknowledge the interrupt (if supported by the chip) */

#ifndef CONFIG_ARCH_NOINTC
       up_maskack_irq(irq);
#endif

       /* Deliver the IRQ */

       irq_dispatch(irq, regs);

       /* Get the current value of regs... it may have changed because
        * of a context switch performed during interrupt processing.
        */

       regs = current_regs;

       /* Restore the previous value of current_regs.  NULL would indicate that
        * we are no longer in an interrupt handler.  It will be non-NULL if we
        * are returning from a nested interrupt.
        */

       current_regs = savestate;

       /* Unmask the last interrupt (global interrupts are still
        * disabled.
        */

#ifndef CONFIG_ARCH_NOINTC
       up_enable_irq(irq);
#endif
    }
  up_ledoff(LED_INIRQ);
#endif
  return regs;
}
void up_decodeirq(uint32_t *regs)
{
#ifdef CONFIG_SUPPRESS_INTERRUPTS
    lowsyslog("Unexpected IRQ\n");
    current_regs = regs;
    PANIC();
#else
    int index;
    int irq;

    /* Read the IRQ vector status register.  Bits 3-10 provide the IRQ number
     * of the interrupt (the TABLE_ADDR was initialized to zero, so the
     * following masking should be unnecessary)
     */

    index = getreg32(LPC31_INTC_VECTOR0) & INTC_VECTOR_INDEX_MASK;
    if (index != 0)
    {
        /* Shift the index so that the range of IRQ numbers are in bits 0-7 (values
         * 1-127) and back off the IRQ number by 1 so that the numbering is zero-based
         */

        irq = (index >> INTC_VECTOR_INDEX_SHIFT) -1;

        /* Verify that the resulting IRQ number is valid */

        if ((unsigned)irq < NR_IRQS)
        {
            /* Mask and acknowledge the interrupt */

            up_maskack_irq(irq);

            /* Current regs non-zero indicates that we are processing an interrupt;
             * current_regs is also used to manage interrupt level context switches.
             *
             * Nested interrupts are not supported.
             */

            DEBUGASSERT(current_regs == NULL);
            current_regs = regs;

            /* Deliver the IRQ */

            irq_dispatch(irq, regs);

#if defined(CONFIG_ARCH_FPU) || defined(CONFIG_ARCH_ADDRENV)
            /* Check for a context switch.  If a context switch occurred, then
             * current_regs will have a different value than it did on entry.
             * If an interrupt level context switch has occurred, then restore
             * the floating point state and the establish the correct address
             * environment before returning from the interrupt.
             */

            if (regs != current_regs)
            {
#ifdef CONFIG_ARCH_FPU
                /* Restore floating point registers */

                up_restorefpu((uint32_t*)current_regs);
#endif

#ifdef CONFIG_ARCH_ADDRENV
                /* Make sure that the address environment for the previously
                 * running task is closed down gracefully (data caches dump,
                 * MMU flushed) and set up the address environment for the new
                 * thread at the head of the ready-to-run list.
                 */

                (void)group_addrenv(NULL);
#endif
            }
#endif
            /* Set current_regs to NULL to indicate that we are no longer in an
             * interrupt handler.
             */

            current_regs = NULL;

            /* Unmask the last interrupt (global interrupts are still
             * disabled).
             */

            up_enable_irq(irq);
        }
    }
Пример #13
0
uint32_t *arm_doirq(int irq, uint32_t *regs)
{
  board_led_on(LED_INIRQ);
#ifdef CONFIG_SUPPRESS_INTERRUPTS
  PANIC();
#else
  /* Nested interrupts are not supported */

  DEBUGASSERT(current_regs == NULL);

  /* Current regs non-zero indicates that we are processing an interrupt;
   * current_regs is also used to manage interrupt level context switches.
   */

  current_regs = regs;

  /* Mask and acknowledge the interrupt */

  up_maskack_irq(irq);

  /* Deliver the IRQ */

  irq_dispatch(irq, regs);

#if defined(CONFIG_ARCH_FPU) || defined(CONFIG_ARCH_ADDRENV)
  /* Check for a context switch.  If a context switch occurred, then
   * current_regs will have a different value than it did on entry.  If an
   * interrupt level context switch has occurred, then restore the floating
   * point state and the establish the correct address environment before
   * returning from the interrupt.
   */

  if (regs != current_regs)
    {
#ifdef CONFIG_ARCH_FPU
      /* Restore floating point registers */

      up_restorefpu((uint32_t*)current_regs);
#endif

#ifdef CONFIG_ARCH_ADDRENV
      /* Make sure that the address environment for the previously
       * running task is closed down gracefully (data caches dump,
       * MMU flushed) and set up the address environment for the new
       * thread at the head of the ready-to-run list.
       */

      (void)group_addrenv(NULL);
#endif
    }
#endif

  /* Set current_regs to NULL to indicate that we are no longer in an
   * interrupt handler.
   */

  regs         = (uint32_t *)current_regs;
  current_regs = NULL;

  /* Unmask the last interrupt (global interrupts are still disabled) */

  up_enable_irq(irq);
#endif

  board_led_off(LED_INIRQ);
  return regs;
}