Example #1
0
void up_sigdeliver(void)
{
#ifndef CONFIG_DISABLE_SIGNALS
  FAR _TCB  *rtcb = (_TCB*)g_readytorun.head;
  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;

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

  up_ledoff(LED_SIGNAL);
  ez80_restorecontext(regs);
#endif
}
Example #2
0
void up_decodeirq(uint32_t *regs)
{
#ifdef CONFIG_SUPPRESS_INTERRUPTS
  up_ledon(LED_INIRQ);
  lib_lowprintf("Unexpected IRQ\n");
  current_regs = regs;
  PANIC(OSERR_ERREXCEPTION);
#else
  unsigned int irq;

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

  up_ledon(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(OSERR_ERREXCEPTION); /* Normally never happens */
    }
#endif
  up_ledoff(LED_INIRQ);
#endif
}
Example #3
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;

  /* Disable further occurences of this interrupt (until the interrupt sources
   * have been clear by the driver.
   */

  up_disable_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;
}
Example #4
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;
}
Example #5
0
uint32_t *isr_handler(uint32_t *regs)
{
#ifdef CONFIG_SUPPRESS_INTERRUPTS
  up_ledon(LED_INIRQ);
  PANIC(OSERR_ERREXCEPTION); /* Doesn't return */
  return regs;               /* To keep the compiler happy */
#else
  uint32_t *ret;

  /* Dispatch the interrupt */

  up_ledon(LED_INIRQ);
  ret = common_handler((int)regs[REG_IRQNO], regs);
  up_ledoff(LED_INIRQ);
  return ret;
#endif
}
Example #6
0
uint8_t *up_doirq(int irq, uint8_t *regs)
{
  up_ledon(LED_INIRQ);
#ifdef CONFIG_SUPPRESS_INTERRUPTS
  PANIC(OSERR_ERREXCEPTION);
#else
  uint8_t *savestate;

  /* Nested interrupts are not supported in this implementation.  If you want
   * implemented nested interrupts, you would have to (1) change the way that
   * current regs is handled and (2) the design associated with
   * CONFIG_ARCH_INTERRUPTSTACK.
   */

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

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

  /* 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 = (uint8_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
  up_ledoff(LED_INIRQ);
  return regs;
}
Example #7
0
static void _up_assert(int errorcode)
{
  /* Are we in an interrupt handler or the idle task? */

  if (current_regs || ((struct tcb_s*)g_readytorun.head)->pid == 0)
    {
       (void)irqsave();
        for(;;)
          {
#ifdef CONFIG_ARCH_LEDS
            up_ledon(LED_PANIC);
            up_mdelay(250);
            up_ledoff(LED_PANIC);
            up_mdelay(250);
#endif
          }
    }
  else
    {
      exit(errorcode);
    }
}
Example #8
0
static void _up_assert(int errorcode) /* __attribute__ ((noreturn)) */
{
  /* Are we in an interrupt handler or the idle task? */

  if (up_interrupt_context() || ((FAR _TCB*)g_readytorun.head)->pid == 0)
    {
       (void)irqsave();
        for(;;)
          {
#ifdef CONFIG_ARCH_LEDS
            up_ledon(LED_PANIC);
            up_mdelay(250);
            up_ledoff(LED_PANIC);
            up_mdelay(250);
#endif
          }
    }
  else
    {
      exit(errorcode);
    }
}
Example #9
0
uint32_t *irq_handler(uint32_t *regs)
{
#ifdef CONFIG_SUPPRESS_INTERRUPTS
  up_ledon(LED_INIRQ);
  PANIC(OSERR_ERREXCEPTION); /* Doesn't return */
  return regs;               /* To keep the compiler happy */
#else
  uint32_t *ret;
  int irq;

  up_ledon(LED_INIRQ);

  /* Get the IRQ number */

  irq = (int)regs[REG_IRQNO];

  /* Send an EOI (end of interrupt) signal to the PICs if this interrupt
   * involved the slave.
   */

  if (irq >= IRQ8)
    {
      /* Send reset signal to slave */

      idt_outb(PIC_OCW2_EOI_NONSPEC, PIC2_OCW2);
    }

  /* Send reset signal to master */

  idt_outb(PIC_OCW2_EOI_NONSPEC, PIC1_OCW2);

  /* Dispatch the interrupt */

  ret = common_handler(irq, regs);
  up_ledoff(LED_INIRQ);
  return ret;
#endif
}
Example #10
0
void up_idle(void)
{
#if defined(CONFIG_ARCH_LEDS) && defined(CONFIG_ARCH_BRINGUP)
  g_ledtoggle++;
  if (g_ledtoggle == 0x80)
    {
      up_ledon(LED_IDLE);
    }
  else if (g_ledtoggle == 0x00)
    {
      up_ledoff(LED_IDLE);
    }
#endif

#if defined(CONFIG_SUPPRESS_INTERRUPTS) || defined(CONFIG_SUPPRESS_TIMER_INTS)
  /* If the system is idle and there are no timer interrupts,
   * then process "fake" timer interrupts. Hopefully, something
   * will wake up.
   */

  sched_process_timer();
#endif
}
Example #11
0
FAR chipreg_t *up_doirq(uint8_t irq, FAR chipreg_t *regs)
{
  up_ledon(LED_INIRQ);

#ifdef CONFIG_SUPPRESS_INTERRUPTS

  lowsyslog("Unexpected IRQ\n");
  IRQ_ENTER(regs);
  PANIC();
  return NULL; /* Won't get here */

#else
  if (irq < NR_IRQS)
    {
       DECL_SAVESTATE();

       /* Indicate that we have entered IRQ processing logic */

       IRQ_ENTER(irq, regs);

       /* Deliver the IRQ */

       irq_dispatch(irq, regs);

       /* If a context switch occurred, 'regs' will hold the new context */

       regs = IRQ_STATE();

       /* Indicate that we are no longer in interrupt processing logic */

       IRQ_LEAVE(irq);
    }

  up_ledoff(LED_INIRQ);
  return regs;
#endif
}
Example #12
0
void up_sigdeliver(void)
{
  struct tcb_s *rtcb = (struct tcb_s*)g_readytorun.head;
  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;

  up_ledon(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_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 */

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

  svdbg("Resuming EPC: %08x STATUS: %08x\n", regs[REG_EPC], regs[REG_STATUS]);

  (void)irqsave();
  rtcb->pterrno = saved_errno;

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

  up_ledoff(LED_SIGNAL);
  up_fullcontextrestore(regs);

  /* up_fullcontextrestore() should not return but could if the software
   * interrupts are disabled.
   */

  PANIC();
}
Example #13
0
void up_sigdeliver(void)
{
  _TCB  *rtcb = (_TCB*)g_readytorun.head;
#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;

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

  irqrestore(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)irqsave();
  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.
   */

  up_ledoff(LED_SIGNAL);
  up_fullcontextrestore(regs);
}
Example #14
0
int nsh_archinitialize(void)
{
  int result;

  /* INIT 1 Lowest level NuttX initialization has been done at this point, LEDs and UARTs are configured */

  /* INIT 2 Configuring PX4 low-level peripherals, these will be always needed */

  /* configure the high-resolution time/callout interface */
#ifdef CONFIG_HRT_TIMER
  hrt_init();
#endif

  /* configure CPU load estimation */
  #ifdef CONFIG_SCHED_INSTRUMENTATION
  cpuload_initialize_once();
  #endif

  /* set up the serial DMA polling */
#ifdef SERIAL_HAVE_DMA
  {
    static struct hrt_call serial_dma_call;
    struct timespec ts;

    /* 
     * Poll at 1ms intervals for received bytes that have not triggered
     * a DMA event.
     */
    ts.tv_sec = 0;
    ts.tv_nsec = 1000000;

    hrt_call_every(&serial_dma_call, 
                   ts_to_abstime(&ts),
                   ts_to_abstime(&ts),
                   (hrt_callout)stm32_serial_dma_poll,
                   NULL);
  }
#endif

  message("\r\n");

  up_ledoff(LED_BLUE);
  up_ledoff(LED_AMBER);

  up_ledon(LED_BLUE);

  /* Configure user-space led driver */
  px4fmu_led_init();

  /* Configure SPI-based devices */

  spi1 = up_spiinitialize(1);
  if (!spi1)
  {
	  message("[boot] FAILED to initialize SPI port 1\r\n");
	  up_ledon(LED_AMBER);
	  return -ENODEV;
  }

  // Setup 10 MHz clock (maximum rate the BMA180 can sustain)
  SPI_SETFREQUENCY(spi1, 10000000);
  SPI_SETBITS(spi1, 8);
  SPI_SETMODE(spi1, SPIDEV_MODE3);
  SPI_SELECT(spi1, PX4_SPIDEV_GYRO, false);
  SPI_SELECT(spi1, PX4_SPIDEV_ACCEL, false);
  SPI_SELECT(spi1, PX4_SPIDEV_MPU, false);
  up_udelay(20);

  message("[boot] Successfully initialized SPI port 1\r\n");

  /* initialize SPI peripherals redundantly */
  int gyro_attempts = 0;
  int gyro_fail = 0;

  while (gyro_attempts < 5)
  {
	  gyro_fail = l3gd20_attach(spi1, PX4_SPIDEV_GYRO);
	  gyro_attempts++;
	  if (gyro_fail == 0) break;
	  up_udelay(1000);
  }

  if (gyro_fail) message("[boot] FAILED to attach L3GD20 gyro\r\n");

  int acc_attempts = 0;
  int acc_fail = 0;

  while (acc_attempts < 5)
  {
	  acc_fail = bma180_attach(spi1, PX4_SPIDEV_ACCEL);
	  acc_attempts++;
	  if (acc_fail == 0) break;
	  up_udelay(1000);
  }

  if (acc_fail) message("[boot] FAILED to attach BMA180 accelerometer\r\n");

  int mpu_attempts = 0;
  int mpu_fail = 0;

  while (mpu_attempts < 1)
  {
	  mpu_fail = mpu6000_attach(spi1, PX4_SPIDEV_MPU);
	  mpu_attempts++;
	  if (mpu_fail == 0) break;
	  up_udelay(200);
  }

  if (mpu_fail) message("[boot] FAILED to attach MPU 6000 gyro/acc\r\n");

  /* initialize I2C2 bus */

  i2c2 = up_i2cinitialize(2);
  if (!i2c2) {
	  message("[boot] FAILED to initialize I2C bus 2\r\n");
	  up_ledon(LED_AMBER);
	  return -ENODEV;
  }

  /* set I2C2 speed */
  I2C_SETFREQUENCY(i2c2, 400000);


  i2c3 = up_i2cinitialize(3);
  if (!i2c3) {
	  message("[boot] FAILED to initialize I2C bus 3\r\n");
	  up_ledon(LED_AMBER);
	  return -ENODEV;
  }

  /* set I2C3 speed */
  I2C_SETFREQUENCY(i2c3, 400000);

  int mag_attempts = 0;
  int mag_fail = 0;

  while (mag_attempts < 5)
  {
	  mag_fail = hmc5883l_attach(i2c2);
	  mag_attempts++;
	  if (mag_fail == 0) break;
	  up_udelay(1000);
  }

  if (mag_fail) message("[boot] FAILED to attach HMC5883L magnetometer\r\n");

  int baro_attempts = 0;
  int baro_fail = 0;
  while (baro_attempts < 5)
  {
	  baro_fail = ms5611_attach(i2c2);
	  baro_attempts++;
	  if (baro_fail == 0) break;
	  up_udelay(1000);
  }

  if (baro_fail) message("[boot] FAILED to attach MS5611 baro at addr #1 or #2 (0x76 or 0x77)\r\n");

  /* try to attach, don't fail if device is not responding */
  (void)eeprom_attach(i2c3, FMU_BASEBOARD_EEPROM_ADDRESS,
		  FMU_BASEBOARD_EEPROM_TOTAL_SIZE_BYTES,
		  FMU_BASEBOARD_EEPROM_PAGE_SIZE_BYTES,
		  FMU_BASEBOARD_EEPROM_PAGE_WRITE_TIME_US, "/dev/baseboard_eeprom", 1);

  int eeprom_attempts = 0;
  int eeprom_fail;
  while (eeprom_attempts < 5)
  {
	  /* try to attach, fail if device does not respond */
	  eeprom_fail = eeprom_attach(i2c2, FMU_ONBOARD_EEPROM_ADDRESS,
			  FMU_ONBOARD_EEPROM_TOTAL_SIZE_BYTES,
			  FMU_ONBOARD_EEPROM_PAGE_SIZE_BYTES,
			  FMU_ONBOARD_EEPROM_PAGE_WRITE_TIME_US, "/dev/eeprom", 1);
	  eeprom_attempts++;
	  if (eeprom_fail == OK) break;
	  up_udelay(1000);
  }

  if (eeprom_fail) message("[boot] FAILED to attach FMU EEPROM\r\n");

  /* Report back sensor status */
  if (acc_fail || gyro_fail || mag_fail || baro_fail || eeprom_fail)
  {
	  up_ledon(LED_AMBER);
  }

#if defined(CONFIG_STM32_SPI3)
  /* Get the SPI port */

  message("[boot] Initializing SPI port 3\r\n");
  spi3 = up_spiinitialize(3);
  if (!spi3)
    {
      message("[boot] FAILED to initialize SPI port 3\r\n");
      up_ledon(LED_AMBER);
      return -ENODEV;
    }
  message("[boot] Successfully initialized SPI port 3\r\n");

  /* Now bind the SPI interface to the MMCSD driver */
  result = mmcsd_spislotinitialize(CONFIG_NSH_MMCSDMINOR, CONFIG_NSH_MMCSDSLOTNO, spi3);
  if (result != OK)
  {
	  message("[boot] FAILED to bind SPI port 3 to the MMCSD driver\r\n");
	  up_ledon(LED_AMBER);
	  return -ENODEV;
  }
  message("[boot] Successfully bound SPI port 3 to the MMCSD driver\r\n");
#endif /* SPI3 */

  /* initialize I2C1 bus */

  i2c1 = up_i2cinitialize(1);
  if (!i2c1) {
    message("[boot] FAILED to initialize I2C bus 1\r\n");
    up_ledon(LED_AMBER);
    return -ENODEV;
  }

  /* set I2C1 speed */
  I2C_SETFREQUENCY(i2c1, 400000);

  /* INIT 3: MULTIPORT-DEPENDENT INITIALIZATION */

  /* Get board information if available */

    /* Initialize the user GPIOs */
  px4fmu_gpio_init();

#ifdef CONFIG_ADC
  int adc_state = adc_devinit();
  if (adc_state != OK)
  {
    /* Try again */
    adc_state = adc_devinit();
    if (adc_state != OK)
    {
      /* Give up */
      message("[boot] FAILED adc_devinit: %d\r\n", adc_state);
      return -ENODEV;
    }
  }
#endif

    /* configure the tone generator */
#ifdef CONFIG_TONE_ALARM
  tone_alarm_init();
#endif

  return OK;
}
Example #15
0
uint32_t *pic32mx_decodeirq(uint32_t *regs)
{
#ifdef CONFIG_SUPPRESS_INTERRUPTS

  up_ledon(LED_INIRQ);
  PANIC(OSERR_ERREXCEPTION);
  up_ledoff(LED_INIRQ); /* Won't get here */
  return regs;

#else
  uint32_t *savestate;
  uint32_t regval;
  int irq;

  /* If the board supports LEDs, turn on an LED now to indicate that we are
   * processing an interrupt.
   */

  up_ledon(LED_INIRQ);

  /* Save the current value of current_regs (to support nested interrupt
   * handling).  Then set current_regs to regs, indicating that this is
   * the interrupted context that is being processed now.
   */

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

  /* Loop while there are pending interrupts with priority greater than zero */

  for (;;)
    {
      /* Read the INTSTAT register.  This register contains both the priority
       * and the interrupt vector number.
       */

      regval = getreg32(PIC32MX_INT_INTSTAT);
      if ((regval & INT_INTSTAT_RIPL_MASK) == 0)
        {
          /* Break out of the loop when the priority is zero meaning that
           * there are no further pending interrupts.
           */

          break;
        }

      /* Get the vector number.  The IRQ numbers have been arranged so that
       * vector numbers and NuttX IRQ numbers are the same value.
       */

      irq = ((regval) & INT_INTSTAT_VEC_MASK) >> INT_INTSTAT_VEC_SHIFT;
      
      /* Disable further interrupts from this source until the driver has
       * cleared the pending interrupt sources.
       */

      up_disable_irq(irq);

      /* Deliver the IRQ */

      irq_dispatch(irq, regs);

      /* Unmask the last interrupt (global interrupt below the current interrupt
       * level are are still disabled)
       */

      up_enable_irq(irq);
    }

  /* 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;
  if (current_regs == NULL)
    {
      up_ledoff(LED_INIRQ);
    }

  return regs;
#endif
}
Example #16
0
uint32_t *pic32mx_decodeirq(uint32_t *regs)
{
#ifdef CONFIG_PIC32MX_NESTED_INTERRUPTS
  uint32_t *savestate;
#endif
  uint32_t regval;
  int irq;

  /* If the board supports LEDs, turn on an LED now to indicate that we are
   * processing an interrupt.
   */

  up_ledon(LED_INIRQ);

  /* Save the current value of current_regs (to support nested interrupt
   * handling).  Then set current_regs to regs, indicating that this is
   * the interrupted context that is being processed now.
   */

#ifdef CONFIG_PIC32MX_NESTED_INTERRUPTS
  savestate = (uint32_t*)current_regs;
#else
  DEBUGASSERT(current_regs == NULL);
#endif
  current_regs = regs;

  /* Loop while there are pending interrupts with priority greater than zero */

  for (;;)
    {
      /* Read the INTSTAT register.  This register contains both the priority
       * and the interrupt vector number.
       */

      regval = getreg32(PIC32MX_INT_INTSTAT);
      if ((regval & INT_INTSTAT_RIPL_MASK) == 0)
        {
          /* Break out of the loop when the priority is zero meaning that
           * there are no further pending interrupts.
           */

          break;
        }

      /* Get the vector number.  The IRQ numbers have been arranged so that
       * vector numbers and NuttX IRQ numbers are the same value.
       */

      irq = ((regval) & INT_INTSTAT_VEC_MASK) >> INT_INTSTAT_VEC_SHIFT;

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

#ifdef CONFIG_PIC32MX_NESTED_INTERRUPTS
  /* I think there are some task switching issues here.  You should not
   * enable nested interrupts unless you are ready to deal with the
   * complexities of nested context switching.  The logic here is probably
   * insufficient.
   */

  current_regs = savestate;
  if (current_regs == NULL)
    {
      up_ledoff(LED_INIRQ);
    }
#else
  current_regs = NULL;
  up_ledoff(LED_INIRQ);
#endif

  return regs;
}
Example #17
0
__EXPORT int nsh_archinitialize(void)
{
	int result;

	/* configure the high-resolution time/callout interface */
#ifdef CONFIG_HRT_TIMER
	hrt_init();
#endif

	/* configure CPU load estimation */
#ifdef CONFIG_SCHED_INSTRUMENTATION
	cpuload_initialize_once();
#endif

	/* set up the serial DMA polling */
#ifdef SERIAL_HAVE_DMA
	{
		static struct hrt_call serial_dma_call;
		struct timespec ts;

		/*
		 * Poll at 1ms intervals for received bytes that have not triggered
		 * a DMA event.
		 */
		ts.tv_sec = 0;
		ts.tv_nsec = 1000000;

		hrt_call_every(&serial_dma_call,
			       ts_to_abstime(&ts),
			       ts_to_abstime(&ts),
			       (hrt_callout)stm32_serial_dma_poll,
			       NULL);
	}
#endif

	message("\r\n");

	// initial LED state
	drv_led_start();
	up_ledoff(LED_BLUE);
	up_ledoff(LED_AMBER);
	up_ledon(LED_BLUE);

	/* Configure SPI-based devices */

	spi1 = up_spiinitialize(1);

	if (!spi1) {
		message("[boot] FAILED to initialize SPI port 1\r\n");
		up_ledon(LED_AMBER);
		return -ENODEV;
	}

	// Default SPI1 to 1MHz and de-assert the known chip selects.
	SPI_SETFREQUENCY(spi1, 10000000);
	SPI_SETBITS(spi1, 8);
	SPI_SETMODE(spi1, SPIDEV_MODE3);
	SPI_SELECT(spi1, PX4_SPIDEV_GYRO, false);
	SPI_SELECT(spi1, PX4_SPIDEV_ACCEL, false);
	SPI_SELECT(spi1, PX4_SPIDEV_MPU, false);
	up_udelay(20);

	message("[boot] Successfully initialized SPI port 1\r\n");

	/* Get the SPI port for the microSD slot */

	message("[boot] Initializing SPI port 3\n");
	spi3 = up_spiinitialize(3);

	if (!spi3) {
		message("[boot] FAILED to initialize SPI port 3\n");
		up_ledon(LED_AMBER);
		return -ENODEV;
	}

	message("[boot] Successfully initialized SPI port 3\n");

	/* Now bind the SPI interface to the MMCSD driver */
	result = mmcsd_spislotinitialize(CONFIG_NSH_MMCSDMINOR, CONFIG_NSH_MMCSDSLOTNO, spi3);

	if (result != OK) {
		message("[boot] FAILED to bind SPI port 3 to the MMCSD driver\n");
		up_ledon(LED_AMBER);
		return -ENODEV;
	}

	message("[boot] Successfully bound SPI port 3 to the MMCSD driver\n");

	stm32_configgpio(GPIO_ADC1_IN10);
	stm32_configgpio(GPIO_ADC1_IN11);
	//stm32_configgpio(GPIO_ADC1_IN12);	// XXX is this available?
	//stm32_configgpio(GPIO_ADC1_IN13);	// jumperable to MPU6000 DRDY on some boards

	return OK;
}
Example #18
0
int nsh_archinitialize(void)
{
  int result;

  /* INIT 1 Lowest level NuttX initialization has been done at this point, LEDs and UARTs are configured */

  /* INIT 2 Configuring PX4 low-level peripherals, these will be always needed */

  /* configure the high-resolution time/callout interface */
#ifdef CONFIG_HRT_TIMER
  hrt_init();
#endif

  /* configure CPU load estimation */
  #ifdef CONFIG_SCHED_INSTRUMENTATION
  cpuload_initialize_once();
  #endif

  /* set up the serial DMA polling */
#ifdef SERIAL_HAVE_DMA
  {
    static struct hrt_call serial_dma_call;
    struct timespec ts;

    /* 
     * Poll at 1ms intervals for received bytes that have not triggered
     * a DMA event.
     */
    ts.tv_sec = 0;
    ts.tv_nsec = 1000000;

    hrt_call_every(&serial_dma_call, 
                   ts_to_abstime(&ts),
                   ts_to_abstime(&ts),
                   (hrt_callout)stm32_serial_dma_poll,
                   NULL);
  }
#endif

  message("\r\n");

  up_ledoff(LED_BLUE);
  up_ledoff(LED_AMBER);

  up_ledon(LED_BLUE);

  /* Configure user-space led driver */
  px4fmu_led_init();


  i2c2 = up_i2cinitialize(2);
  if (!i2c2) {
	  message("[boot] FAILED to initialize I2C bus 3\r\n");
	  up_ledon(LED_AMBER);
	  return -ENODEV;
  }

  /* set I2C3 speed */
  I2C_SETFREQUENCY(i2c2, 400000);

  /* try to attach, don't fail if device is not responding */
  (void)eeprom_attach(i2c2, FMU_BASEBOARD_EEPROM_ADDRESS,
		  FMU_BASEBOARD_EEPROM_TOTAL_SIZE_BYTES,
		  FMU_BASEBOARD_EEPROM_PAGE_SIZE_BYTES,
		  FMU_BASEBOARD_EEPROM_PAGE_WRITE_TIME_US, "/dev/baseboard_eeprom", 1);

  int eeprom_attempts = 0;
  int eeprom_fail;
  while (eeprom_attempts < 5)
  {
	  /* try to attach, fail if device does not respond */
	  eeprom_fail = eeprom_attach(i2c2, FMU_ONBOARD_EEPROM_ADDRESS,
			  FMU_ONBOARD_EEPROM_TOTAL_SIZE_BYTES,
			  FMU_ONBOARD_EEPROM_PAGE_SIZE_BYTES,
			  FMU_ONBOARD_EEPROM_PAGE_WRITE_TIME_US, "/dev/eeprom", 1);
	  eeprom_attempts++;
	  if (eeprom_fail == OK) break;
	  up_udelay(1000);
  }

  if (eeprom_fail) message("[boot] FAILED to attach FMU EEPROM\r\n");

  /* Report back sensor status */
  if (eeprom_fail)
  {
	  up_ledon(LED_AMBER);
  }

#if defined(CONFIG_STM32_SPI3)
  /* Get the SPI port */

  message("[boot] Initializing SPI port 3\r\n");
  spi3 = up_spiinitialize(3);
  if (!spi3)
    {
      message("[boot] FAILED to initialize SPI port 3\r\n");
      up_ledon(LED_AMBER);
      return -ENODEV;
    }
  message("[boot] Successfully initialized SPI port 3\r\n");

  /* Now bind the SPI interface to the MMCSD driver */
  result = mmcsd_spislotinitialize(CONFIG_NSH_MMCSDMINOR, CONFIG_NSH_MMCSDSLOTNO, spi3);
  if (result != OK)
  {
	  message("[boot] FAILED to bind SPI port 3 to the MMCSD driver\r\n");
	  up_ledon(LED_AMBER);
	  return -ENODEV;
  }
  message("[boot] Successfully bound SPI port 3 to the MMCSD driver\r\n");
#endif /* SPI3 */

  /* INIT 3: MULTIPORT-DEPENDENT INITIALIZATION */

  /* Get board information if available */

    /* Initialize the user GPIOs */
  px4fmu_gpio_init();

#ifdef CONFIG_ADC
  int adc_state = adc_devinit();
  if (adc_state != OK)
  {
    /* Try again */
    adc_state = adc_devinit();
    if (adc_state != OK)
    {
      /* Give up */
      message("[boot] FAILED adc_devinit: %d\r\n", adc_state);
      return -ENODEV;
    }
  }
#endif

    /* configure the tone generator */
#ifdef CONFIG_TONE_ALARM
  tone_alarm_init();
#endif

  return OK;
}
Example #19
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;
}