Пример #1
0
static void queues1_execute(void) {
  unsigned i;
  size_t n;

  /* Initial empty state */
  test_assert(1, chIQIsEmptyI(&iq), "not empty");

  /* Queue filling */
  for (i = 0; i < TEST_QUEUES_SIZE; i++)
    chIQPutI(&iq, 'A' + i);
  test_assert(2, chIQIsFullI(&iq), "still has space");
  test_assert(3, chIQPutI(&iq, 0) == Q_FULL, "failed to report Q_FULL");

  /* Queue emptying */
  for (i = 0; i < TEST_QUEUES_SIZE; i++)
    test_emit_token(chIQGet(&iq));
  test_assert(4, chIQIsEmptyI(&iq), "still full");
  test_assert_sequence(5, "ABCD");

  /* Queue filling again */
  for (i = 0; i < TEST_QUEUES_SIZE; i++)
    chIQPutI(&iq, 'A' + i);

  /* Reading the whole thing */
  n = chIQReadTimeout(&iq, wa[1], TEST_QUEUES_SIZE * 2, TIME_IMMEDIATE);
  test_assert(6, n == TEST_QUEUES_SIZE, "wrong returned size");
  test_assert(7, chIQIsEmptyI(&iq), "still full");

  /* Queue filling again */
  for (i = 0; i < TEST_QUEUES_SIZE; i++)
    chIQPutI(&iq, 'A' + i);

  /* Partial reads */
  n = chIQReadTimeout(&iq, wa[1], TEST_QUEUES_SIZE / 2, TIME_IMMEDIATE);
  test_assert(8, n == TEST_QUEUES_SIZE / 2, "wrong returned size");
  n = chIQReadTimeout(&iq, wa[1], TEST_QUEUES_SIZE / 2, TIME_IMMEDIATE);
  test_assert(9, n == TEST_QUEUES_SIZE / 2, "wrong returned size");
  test_assert(10, chIQIsEmptyI(&iq), "still full");

  /* Testing reset */
  chIQPutI(&iq, 0);
  chIQResetI(&iq);
  test_assert(11, chIQGetFullI(&iq) == 0, "still full");
  threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority()+1, thread1, NULL);
  test_assert(12, chIQGetFullI(&iq) == 0, "not empty");
  test_wait_threads();

  /* Timeout */
  test_assert(13, chIQGetTimeout(&iq, 10) == Q_TIMEOUT, "wrong timeout return");
}
Пример #2
0
/**
 * @brief   Input queue read with timeout.
 * @details The function reads data from an input queue into a buffer. The
 *          operation completes when the specified amount of data has been
 *          transferred or after the specified timeout or if the queue has
 *          been reset.
 * @note    The function is not atomic, if you need atomicity it is suggested
 *          to use a semaphore or a mutex for mutual exclusion.
 * @note    The callback is invoked before reading each character from the
 *          buffer or before entering the state @p CH_STATE_WTQUEUE.
 *
 * @param[in] iqp       pointer to an @p input_queue_t structure
 * @param[out] bp       pointer to the data buffer
 * @param[in] n         the maximum amount of data to be transferred, the
 *                      value 0 is reserved
 * @param[in] time      the number of ticks before the operation timeouts,
 *                      the following special values are allowed:
 *                      - @a TIME_IMMEDIATE immediate timeout.
 *                      - @a TIME_INFINITE no timeout.
 *                      .
 * @return              The number of bytes effectively transferred.
 *
 * @api
 */
size_t chIQReadTimeout(input_queue_t *iqp, uint8_t *bp,
                       size_t n, systime_t time) {
  qnotify_t nfy = iqp->q_notify;
  size_t r = 0;

  chDbgCheck(n > 0);

  chSysLock();
  while (true) {
    if (nfy)
      nfy(iqp);

    while (chIQIsEmptyI(iqp)) {
      if (chThdEnqueueTimeoutS(&iqp->q_waiting, time) != Q_OK) {
        chSysUnlock();
        return r;
      }
    }

    iqp->q_counter--;
    *bp++ = *iqp->q_rdptr++;
    if (iqp->q_rdptr >= iqp->q_top)
      iqp->q_rdptr = iqp->q_buffer;

    chSysUnlock(); /* Gives a preemption chance in a controlled point.*/
    r++;
    if (--n == 0)
      return r;

    chSysLock();
  }
}
Пример #3
0
/**
 * @brief   Input queue read with timeout.
 * @details This function reads a byte value from an input queue. If the queue
 *          is empty then the calling thread is suspended until a byte arrives
 *          in the queue or a timeout occurs.
 * @note    The callback is invoked before reading the character from the
 *          buffer or before entering the state @p CH_STATE_WTQUEUE.
 *
 * @param[in] iqp       pointer to an @p input_queue_t structure
 * @param[in] timeout   the number of ticks before the operation timeouts,
 *                      the following special values are allowed:
 *                      - @a TIME_IMMEDIATE immediate timeout.
 *                      - @a TIME_INFINITE no timeout.
 *                      .
 * @return              A byte value from the queue.
 * @retval Q_TIMEOUT    if the specified time expired.
 * @retval Q_RESET      if the queue has been reset.
 *
 * @api
 */
msg_t chIQGetTimeout(input_queue_t *iqp, systime_t timeout) {
    uint8_t b;

    chSysLock();
    if (iqp->notify != NULL) {
        iqp->notify(iqp);
    }

    while (chIQIsEmptyI(iqp)) {
        msg_t msg = chThdEnqueueTimeoutS(&iqp->waiting, timeout);
        if (msg < Q_OK) {
            chSysUnlock();
            return msg;
        }
    }

    iqp->counter--;
    b = *iqp->rdptr++;
    if (iqp->rdptr >= iqp->top) {
        iqp->rdptr = iqp->buffer;
    }
    chSysUnlock();

    return (msg_t)b;
}
Пример #4
0
/**
 * @brief   Input queue read with timeout.
 * @details The function reads data from an input queue into a buffer. The
 *          operation completes when the specified amount of data has been
 *          transferred or after the specified timeout or if the queue has
 *          been reset.
 * @note    The function is not atomic, if you need atomicity it is suggested
 *          to use a semaphore or a mutex for mutual exclusion.
 * @note    The callback is invoked before reading each character from the
 *          buffer or before entering the state @p THD_STATE_WTQUEUE.
 *
 * @param[in] iqp       pointer to an @p InputQueue structure
 * @param[out] bp       pointer to the data buffer
 * @param[in] n         the maximum amount of data to be transferred, the
 *                      value 0 is reserved
 * @param[in] time      the number of ticks before the operation timeouts,
 *                      the following special values are allowed:
 *                      - @a TIME_IMMEDIATE immediate timeout.
 *                      - @a TIME_INFINITE no timeout.
 *                      .
 * @return              The number of bytes effectively transferred.
 *
 * @api
 */
size_t chIQReadTimeout(InputQueue *iqp, uint8_t *bp,
                       size_t n, systime_t time) {
    qnotify_t nfy = iqp->q_notify;
    size_t r = 0;

    chDbgCheck(n > 0, "chIQReadTimeout");

    chSysLock();
    while (TRUE) {
        if (nfy)
            nfy(iqp);

        while (chIQIsEmptyI(iqp)) {
            if (qwait((GenericQueue *)iqp, time) != Q_OK) {
                chSysUnlock();
                return r;
            }
        }

        iqp->q_counter--;
        *bp++ = *iqp->q_rdptr++;
        if (iqp->q_rdptr >= iqp->q_top)
            iqp->q_rdptr = iqp->q_buffer;

        chSysUnlock(); /* Gives a preemption chance in a controlled point.*/
        r++;
        if (--n == 0)
            return r;

        chSysLock();
    }
}
Пример #5
0
/**
 * @brief   Common IRQ handler.
 * @note    Tries hard to clear all the pending interrupt sources, we don't
 *          want to go through the whole ISR and have another interrupt soon
 *          after.
 *
 * @param[in] u         pointer to an UART I/O block
 * @param[in] sdp       communication channel associated to the UART
 */
static void serve_interrupt(SerialDriver *sdp) {
  UART_TypeDef *u = sdp->uart;
  uint8_t s1 = u->S1;

  if (s1 & UARTx_S1_RDRF) {
    osalSysLockFromISR();
    if (chIQIsEmptyI(&sdp->iqueue))
      chnAddFlagsI(sdp, CHN_INPUT_AVAILABLE);
    if (chIQPutI(&sdp->iqueue, u->D) < Q_OK)
      chnAddFlagsI(sdp, SD_OVERRUN_ERROR);
    osalSysUnlockFromISR();
  }

  if (s1 & UARTx_S1_TDRE) {
    msg_t b;

    osalSysLockFromISR();
    b = chOQGetI(&sdp->oqueue);
    osalSysUnlockFromISR();

    if (b < Q_OK) {
      osalSysLockFromISR();
      chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
      osalSysUnlockFromISR();
      u->C2 &= ~UARTx_C2_TIE;
    } else {
       u->D = b;
    }
  }
}
Пример #6
0
/**
 * @brief   Input queue read with timeout.
 * @details The function reads data from an input queue into a buffer. The
 *          operation completes when the specified amount of data has been
 *          transferred or after the specified timeout or if the queue has
 *          been reset.
 * @note    The function is not atomic, if you need atomicity it is suggested
 *          to use a semaphore or a mutex for mutual exclusion.
 * @note    The queue callback is invoked before entering a sleep state and at
 *          the end of the transfer.
 *
 * @param[in] iqp       pointer to an @p InputQueue structure
 * @param[out] bp       pointer to the data buffer
 * @param[in] n         the maximum amount of data to be transferred, the
 *                      value 0 is reserved
 * @param[in] time      the number of ticks before the operation timeouts,
 *                      the following special values are allowed:
 *                      - @a TIME_IMMEDIATE immediate timeout.
 *                      - @a TIME_INFINITE no timeout.
 *                      .
 * @return              The number of bytes effectively transferred.
 *
 * @api
 */
size_t chIQReadTimeout(InputQueue *iqp, uint8_t *bp,
                       size_t n, systime_t time) {
  qnotify_t nfy = iqp->q_notify;
  size_t r = 0;

  chDbgCheck(n > 0, "chIQReadTimeout");

  chSysLock();
  while (TRUE) {
    if (chIQIsEmptyI(iqp)) {
      if (nfy)
        nfy(iqp);
      if ((chSemWaitTimeoutS(&iqp->q_sem, time) != RDY_OK)) {
        chSysUnlock();
        return r;
      }
    }
    else
      chSemFastWaitI(&iqp->q_sem);
    *bp++ = *iqp->q_rdptr++;
    if (iqp->q_rdptr >= iqp->q_top)
      iqp->q_rdptr = iqp->q_buffer;
    chSysUnlock(); /* Gives a preemption chance in a controlled point.*/
    r++;
    if (--n == 0) {
      chSysLock();
      if (nfy)
        nfy(iqp);
      chSysUnlock();
      return r;
    }
    chSysLock();
  }
}
/**
 * @brief   Handles incoming data.
 * @details This function must be called from the input interrupt service
 *          routine in order to enqueue incoming data and generate the
 *          related events.
 * @note    The incoming data event is only generated when the input queue
 *          becomes non-empty.
 * @note    In order to gain some performance it is suggested to not use
 *          this function directly but copy this code directly into the
 *          interrupt service routine.
 *
 * @param[in] sdp       pointer to a @p SerialDriver structure
 * @param[in] b         the byte to be written in the driver's Input Queue
 *
 * @iclass
 */
void sdIncomingDataI(SerialDriver *sdp, uint8_t b) {

  chDbgCheckClassI();
  chDbgCheck(sdp != NULL, "sdIncomingDataI");

  if (chIQIsEmptyI(&sdp->iqueue))
    chIOAddFlagsI(sdp, IO_INPUT_AVAILABLE);
  if (chIQPutI(&sdp->iqueue, b) < Q_OK)
    chIOAddFlagsI(sdp, SD_OVERRUN_ERROR);
}
Пример #8
0
/**
 * @brief   Common IRQ handler.
 * @note    Tries hard to clear all the pending interrupt sources, we dont want
 *          to go through the whole ISR and have another interrupt soon after.
 *
 * @param[in] sdp       communication channel associated to the UART
 */
static void serve_interrupt(SerialDriver *sdp) {
  UART *u = sdp->uart;

  while (TRUE) {
    switch (u->UART_IIR & IIR_SRC_MASK) {
    case IIR_SRC_NONE:
      return;
    case IIR_SRC_ERROR:
      set_error(sdp, u->UART_LSR);
      break;
    case IIR_SRC_TIMEOUT:
    case IIR_SRC_RX:
      chSysLockFromIsr();
      if (chIQIsEmptyI(&sdp->iqueue))
        chnAddFlagsI(sdp, CHN_INPUT_AVAILABLE);
      chSysUnlockFromIsr();
      while (u->UART_LSR & LSR_RBR_FULL) {
        chSysLockFromIsr();
        if (chIQPutI(&sdp->iqueue, u->UART_RBR) < Q_OK)
          chnAddFlagsI(sdp, SD_OVERRUN_ERROR);
        chSysUnlockFromIsr();
      }
      break;
    case IIR_SRC_TX:
      {
        int i = LPC214x_UART_FIFO_PRELOAD;
        do {
          msg_t b;

          chSysLockFromIsr();
          b = chOQGetI(&sdp->oqueue);
          chSysUnlockFromIsr();
          if (b < Q_OK) {
            u->UART_IER &= ~IER_THRE;
            chSysLockFromIsr();
            chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
            chSysUnlockFromIsr();
            break;
          }
          u->UART_THR = b;
        } while (--i);
      }
      break;
    default:
      (void) u->UART_THR;
      (void) u->UART_RBR;
    }
  }
}
Пример #9
0
/**
 * @brief   Common IRQ handler.
 * @note    Tries hard to clear all the pending interrupt sources, we don't
 *          want to go through the whole ISR and have another interrupt soon
 *          after.
 *
 * @param[in] u         pointer to an UART I/O block
 * @param[in] sdp       communication channel associated to the UART
 */
static void serve_interrupt(SerialDriver *sdp) {
  LPC_USART_TypeDef *u = sdp->uart;

  while (u->INTSTAT) {

    if (u->INTSTAT & STAT_RXRDY) {
      chSysLockFromIsr();
      if (chIQIsEmptyI(&sdp->iqueue))
        chnAddFlagsI(sdp, CHN_INPUT_AVAILABLE);
      if (chIQPutI(&sdp->iqueue, u->RXDATA) < Q_OK)
        chnAddFlagsI(sdp, SD_OVERRUN_ERROR);
      chSysUnlockFromIsr();
    }

    if (u->INTSTAT & STAT_TXRDY) {
      msg_t b;

      chSysLockFromIsr();
      b = chOQGetI(&sdp->oqueue);
      chSysUnlockFromIsr();

      if (b < Q_OK) {
        u->INTENCLR = STAT_TXRDY;
        chSysLockFromIsr();
        chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
        chSysUnlockFromIsr();
        break;
      }
      else {
         u->TXDATA = b;
      }
    }

    if (u->INTSTAT & (STAT_OVERRUN | STAT_DELTARXBRK |
                      STAT_FRAMERR | STAT_PARITYERR) ) {
      IOREG32 stat = u->STAT;
      set_error(sdp, stat);
      u->STAT = stat;
    }

  }
}
Пример #10
0
/**
 * @brief   Input queue read with timeout.
 * @details This function reads a byte value from an input queue. If the queue
 *          is empty then the calling thread is suspended until a byte arrives
 *          in the queue or a timeout occurs.
 * @note    The callback is invoked before reading the character from the
 *          buffer or before entering the state @p CH_STATE_WTQUEUE.
 *
 * @param[in] iqp       pointer to an @p input_queue_t structure
 * @param[in] time      the number of ticks before the operation timeouts,
 *                      the following special values are allowed:
 *                      - @a TIME_IMMEDIATE immediate timeout.
 *                      - @a TIME_INFINITE no timeout.
 *                      .
 * @return              A byte value from the queue.
 * @retval Q_TIMEOUT    if the specified time expired.
 * @retval Q_RESET      if the queue has been reset.
 *
 * @api
 */
msg_t chIQGetTimeout(input_queue_t *iqp, systime_t time) {
  uint8_t b;

  chSysLock();
  if (iqp->q_notify)
    iqp->q_notify(iqp);

  while (chIQIsEmptyI(iqp)) {
    msg_t msg;
    if ((msg = chThdEnqueueTimeoutS(&iqp->q_waiting, time)) < Q_OK) {
      chSysUnlock();
      return msg;
    }
  }

  iqp->q_counter--;
  b = *iqp->q_rdptr++;
  if (iqp->q_rdptr >= iqp->q_top)
    iqp->q_rdptr = iqp->q_buffer;

  chSysUnlock();
  return b;
}
Пример #11
0
/**
 * @brief   Input queue read with timeout.
 * @details This function reads a byte value from an input queue. If the queue
 *          is empty then the calling thread is suspended until a byte arrives
 *          in the queue or a timeout occurs.
 * @note    The callback is invoked before reading the character from the
 *          buffer or before entering the state @p THD_STATE_WTQUEUE.
 *
 * @param[in] iqp       pointer to an @p InputQueue structure
 * @param[in] time      the number of ticks before the operation timeouts,
 *                      the following special values are allowed:
 *                      - @a TIME_IMMEDIATE immediate timeout.
 *                      - @a TIME_INFINITE no timeout.
 *                      .
 * @return              A byte value from the queue.
 * @retval Q_TIMEOUT    if the specified time expired.
 * @retval Q_RESET      if the queue has been reset.
 *
 * @api
 */
msg_t chIQGetTimeout(InputQueue *iqp, systime_t time) {
    uint8_t b;

    chSysLock();
    if (iqp->q_notify)
        iqp->q_notify(iqp);

    while (chIQIsEmptyI(iqp)) {
        msg_t msg;
        if ((msg = qwait((GenericQueue *)iqp, time)) < Q_OK) {
            chSysUnlock();
            return msg;
        }
    }

    iqp->q_counter--;
    b = *iqp->q_rdptr++;
    if (iqp->q_rdptr >= iqp->q_top)
        iqp->q_rdptr = iqp->q_buffer;

    chSysUnlock();
    return b;
}
Пример #12
0
bool InQueue::isEmptyI(void) {

    return (bool)chIQIsEmptyI(&iq);
}
static bool_t getwouldblock(void *ip) {

  return chIQIsEmptyI(&((SerialDriver *)ip)->iqueue);
}