Ejemplo n.º 1
0
static void _up_assert(int errorcode)
{
  /* Flush any buffered SYSLOG data */

  (void)syslog_flush();

  /* Are we in an interrupt handler or the idle task? */

  if (g_current_regs || this_task()->pid == 0)
    {
       (void)up_irq_save();
        for (; ; )
          {
#if CONFIG_BOARD_RESET_ON_ASSERT >= 1
            board_reset(0);
#endif
#ifdef CONFIG_ARCH_LEDS
            board_autoled_on(LED_PANIC);
            up_mdelay(250);
            board_autoled_off(LED_PANIC);
            up_mdelay(250);
#endif
          }
    }
  else
    {
#if CONFIG_BOARD_RESET_ON_ASSERT >= 2
      board_reset(0);
#endif
      exit(errorcode);
    }
}
Ejemplo n.º 2
0
void up_sigdeliver(void)
{
#ifndef CONFIG_DISABLE_SIGNALS
  FAR struct tcb_s *rtcb = this_task();
  chipreg_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);

  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. */

  ez80_copystate(regs, rtcb->xcp.regs);
  regs[XCPT_PC] = rtcb->xcp.saved_pc;
  regs[XCPT_I]  = rtcb->xcp.saved_i;

  /* 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. */

  irqrestore(regs[XCPT_I]);

  /* 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)irqsave();
  rtcb->pterrno = saved_errno;

  /* Then restore the correct state for this thread of
   * execution.
   */

  board_autoled_off(LED_SIGNAL);
  ez80_restorecontext(regs);
#endif
}
Ejemplo n.º 3
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);

	svdbg("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_copyfullstate(regs, rtcb->xcp.regs);
	regs[REG_PC] = rtcb->xcp.saved_pc;
	regs[REG_CPSR] = rtcb->xcp.saved_cpsr;

	/* 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 */

	irqrestore(regs[REG_CPSR]);

	/* 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).
	 */

	svdbg("Resuming\n");
	(void)irqsave();
	rtcb->pterrno = saved_errno;

	/* Then restore the correct state for this thread of execution. */

	board_autoled_off(LED_SIGNAL);
#ifdef CONFIG_TASK_SCHED_HISTORY
	/* Save the task name which will be scheduled */
	save_task_scheduling_status(rtcb);
#endif
	up_fullcontextrestore(regs);
}
Ejemplo n.º 4
0
void up_decodeirq(uint32_t *regs)
{
#ifdef CONFIG_SUPPRESS_INTERRUPTS
  board_autoled_on(LED_INIRQ);
  lowsyslog(LOG_ERR, "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_autoled_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;

      /* Acknowledge the interrupt */

      up_ack_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;
    }
#ifdef CONFIG_DEBUG
  else
    {
      PANIC(); /* Normally never happens */
    }
#endif
  board_autoled_off(LED_INIRQ);
#endif
}
Ejemplo n.º 5
0
uint32_t *up_doirq(int irq, uint32_t *regs)
{
  board_autoled_on(LED_INIRQ);
#ifdef CONFIG_SUPPRESS_INTERRUPTS
  PANIC();
#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;

  /* Acknowledge the interrupt */

  up_ack_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;
#endif
  board_autoled_off(LED_INIRQ);
  return regs;
}
Ejemplo n.º 6
0
static void _up_assert(int errorcode)
{
  /* Are we in an interrupt handler or the idle task? */

  if (g_current_regs || this_task()->pid == 0)
    {
      (void)up_irq_save();
      for (; ; )
        {
#ifdef CONFIG_ARCH_LEDS
          board_autoled_on(LED_PANIC);
          up_mdelay(250);
          board_autoled_off(LED_PANIC);
          up_mdelay(250);
#endif
        }
    }
  else
    {
      exit(errorcode);
    }
}
Ejemplo n.º 7
0
static void _up_assert(int errorcode) /* noreturn_function */
{
  /* Are we in an interrupt handler or the idle task? */

  if (up_interrupt_context() || this_task()->pid == 0)
    {
       (void)irqsave();
        for (;;)
          {
#ifdef CONFIG_ARCH_LEDS
            board_autoled_on(LED_PANIC);
            up_mdelay(250);
            board_autoled_off(LED_PANIC);
            up_mdelay(250);
#endif
          }
    }
  else
    {
      exit(errorcode);
    }
}
Ejemplo n.º 8
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);
}
Ejemplo n.º 9
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();
}
Ejemplo n.º 10
0
uint32_t *up_doirq(int irq, uint32_t* regs)
{
  board_autoled_on(LED_INIRQ);
#ifdef CONFIG_SUPPRESS_INTERRUPTS
  PANIC();
#else
  if ((unsigned)irq < NR_IRQS)
    {
      /* Current regs non-zero indicates that we are processing
       * an interrupt; g_current_regs is also used to manage
       * interrupt level context switches.
       *
       * Nested interrupts are not supported.
       */

      DEBUGASSERT(g_current_regs == NULL);
      g_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
       * g_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 != g_current_regs)
        {
#ifdef CONFIG_ARCH_FPU
          /* Restore floating point registers */

          up_restorefpu((uint32_t*)g_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
      /* Get the current value of regs... it may have changed because
       * of a context switch performed during interrupt processing.
       */

      regs = g_current_regs;

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

      g_current_regs = NULL;
    }

  board_autoled_off(LED_INIRQ);
#endif
  return regs;
}
Ejemplo n.º 11
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);

  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_copyfullstate(regs, rtcb->xcp.regs);
  regs[REG_PC]         = rtcb->xcp.saved_pc;
#ifdef CONFIG_ARMV7M_USEBASEPRI
  regs[REG_BASEPRI]    = rtcb->xcp.saved_basepri;
#else
  regs[REG_PRIMASK]    = rtcb->xcp.saved_primask;
#endif
  regs[REG_XPSR]       = rtcb->xcp.saved_xpsr;
#ifdef CONFIG_BUILD_PROTECTED
  regs[REG_LR]         = rtcb->xcp.saved_lr;
#endif

  /* 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 */

#ifdef CONFIG_ARMV7M_USEBASEPRI
  irqrestore((uint8_t)regs[REG_BASEPRI]);
#else
  irqrestore((uint16_t)regs[REG_PRIMASK]);
#endif

  /* Deliver the signal */

  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)irqsave();
  rtcb->pterrno = saved_errno;

  /* Then restore the correct state for this thread of
   * execution.
   */

  board_autoled_off(LED_SIGNAL);
  up_fullcontextrestore(regs);
}
Ejemplo n.º 12
0
uint8_t *up_doirq(int irq, uint8_t *regs)
{
    board_autoled_on(LED_INIRQ);
#ifdef CONFIG_SUPPRESS_INTERRUPTS
    PANIC();
#else
    /* 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

    /* 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 = (uint8_t*)current_regs;

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

    current_regs = NULL;
#endif
    board_autoled_off(LED_INIRQ);
    return regs;
}