static void *simuart_thread(void *arg)
{
  unsigned char ch;
  ssize_t nread;
  int next;
  int prev;

  /* Now loop, collecting a buffering data from stdin forever */

  for (;;)
    {
      /* Read one character from stdin */

      nread = read(0, &ch, 1);

      /* Check for failures (but don't do anything) */

      if (nread == 1)
        {
#ifdef CONFIG_SIM_UART_DATAPOST
          sched_lock();
#endif

          /* Get the index to the next slot in the UART buffer */

          prev = g_uarthead;
          next = prev + 1;
          if (next >= SIMUART_BUFSIZE)
            {
              next = 0;
            }

          /* Would adding this character cause an overflow? */

          if (next != g_uarttail)
            {
              /* No.. Add the character to the UART buffer */

              g_uartbuffer[prev] = ch;

              /* Update the head index (BEFORE posting) */

              g_uarthead = next;

              /* Was the buffer previously empty? */

              if (prev == g_uarttail)
                {
                  /* Yes.. signal any (NuttX) threads waiting for serial
                   * input.
                   */

#ifdef CONFIG_SIM_UART_DATAPOST
                  simuart_post();
#else
                  g_uart_data_available = 1;
#endif
                }
            }

#ifdef CONFIG_SIM_UART_DATAPOST
          /* REVISIT:  This is very weird and scary here.  When sched_unlock()
           * is called, we may do a lonjmp() style context switch meaning
           * that the logic will be run running on this thread! (but with a
           * different stack).  So we do not get back here until the task
           * sleeps again.  I can't help but believe that that is going to
           * be a problem someday.
           */

          sched_unlock();
#endif
        }
    }

  return NULL;
}
示例#2
0
void up_idle(void)
{
#ifdef CONFIG_SMP
  /* In the SMP configuration, only one CPU should do these operations.  It
   * should not matter which, however.
   */

  static volatile spinlock_t lock;

  /* The one that gets the lock is the one that executes the IDLE operations */

  if (up_testset(&lock) != SP_UNLOCKED)
    {
      /* We didn't get it... Give other pthreads/CPUs a shot and try again
       * later.
       */

      pthread_yield();
      return;
    }
#endif

#ifdef CONFIG_SCHED_TICKLESS
  /* Driver the simulated interval timer */

  up_timer_update();
#else
  /* If the system is idle, then process "fake" timer interrupts.
   * Hopefully, something will wake up.
   */

  sched_process_timer();
#endif

#if defined(CONFIG_DEV_CONSOLE) && !defined(CONFIG_SIM_UART_DATAPOST)
  /* Handle UART data availability */

  if (g_uart_data_available)
    {
      g_uart_data_available = 0;
      simuart_post();
    }
#endif


#ifdef CONFIG_NET_ETHERNET
  /* Run the network if enabled */

  netdriver_loop();
#endif

#ifdef CONFIG_PM
  /* Fake some power management stuff for testing purposes */

  {
    static enum pm_state_e state = PM_NORMAL;
    enum pm_state_e newstate;

    newstate = pm_checkstate();
    if (newstate != state)
      {
        if (pm_changestate(newstate) == OK)
          {
            state = newstate;
          }
      }
  }
#endif

#if defined(CONFIG_SIM_WALLTIME) || defined(CONFIG_SIM_X11FB)
  /* Wait a bit so that the sched_process_timer() is called close to the
   * correct rate.
   */

  (void)up_hostusleep(1000000 / CLK_TCK);

  /* Handle X11-related events */

#ifdef CONFIG_SIM_X11FB
  if (g_x11initialized)
    {
#if defined(CONFIG_SIM_TOUCHSCREEN) || defined(CONFIG_SIM_AJOYSTICK)
       /* Drive the X11 event loop */

      if (g_eventloop)
        {
          up_x11events();
        }
#endif

      /* Update the display periodically */

      g_x11refresh += 1000000 / CLK_TCK;
      if (g_x11refresh > 500000)
        {
          up_x11update();
        }
    }
#endif
#endif

#ifdef CONFIG_SMP
  /* Release the spinlock */

  lock = SP_UNLOCKED;

  /* Give other pthreads/CPUs a shot */

  pthread_yield();
#endif
}