diff options
author | gdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4> | 2009-05-01 12:58:05 +0000 |
---|---|---|
committer | gdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4> | 2009-05-01 12:58:05 +0000 |
commit | 46e56d73491d9141b7ed3f79f2a26d3d9addc8ef (patch) | |
tree | 85ecb54dbfef17991da9e4ce20720b98bfa021ff /src | |
parent | e0073441fe85ae82accf2c0c7e4f329d5e59ed08 (diff) | |
download | ChibiOS-46e56d73491d9141b7ed3f79f2a26d3d9addc8ef.tar.gz ChibiOS-46e56d73491d9141b7ed3f79f2a26d3d9addc8ef.tar.bz2 ChibiOS-46e56d73491d9141b7ed3f79f2a26d3d9addc8ef.zip |
I/O queues improvements, removed half duplex queues.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@926 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'src')
-rw-r--r-- | src/chqueues.c | 518 | ||||
-rw-r--r-- | src/chserial.c | 92 | ||||
-rw-r--r-- | src/include/queues.h | 156 | ||||
-rw-r--r-- | src/include/serial.h | 56 |
4 files changed, 246 insertions, 576 deletions
diff --git a/src/chqueues.c b/src/chqueues.c index b7e14e69d..b1711814d 100644 --- a/src/chqueues.c +++ b/src/chqueues.c @@ -33,250 +33,259 @@ * @details A Semaphore is internally initialized and works as a counter of
* the bytes contained in the queue.
*
- * @param[out] qp pointer to a @p Queue structure
+ * @param[out] iqp pointer to an @p InputQueue structure
* @param[in] buffer pointer to a memory area allocated as queue buffer
* @param[in] size size of the queue buffer
* @param[in] inotify pointer to a callback function that is invoked when
- * some data is read from the Queue. The value can be
-* @p NULL.
+ * some data is read from the queue. The value can be
+ * @p NULL.
+ *
+ * @note The callback is invoked from within the S-Locked system state,
+ * see @ref system_states.
*/
-void chIQInit(Queue *qp, uint8_t *buffer, size_t size, qnotify_t inotify) {
+void chIQInit(InputQueue *iqp, uint8_t *buffer,
+ size_t size, qnotify_t inotify) {
- qp->q_buffer = qp->q_rdptr = qp->q_wrptr = buffer;
- qp->q_top = buffer + size;
- chSemInit(&qp->q_sem, 0);
- qp->q_notify = inotify;
+ iqp->q_buffer = iqp->q_rdptr = iqp->q_wrptr = buffer;
+ iqp->q_top = buffer + size;
+ chSemInit(&iqp->q_sem, 0);
+ iqp->q_notify = inotify;
}
/**
* @brief Resets an input queue.
- * @details All the data is lost and the waiting threads resumed.
+ * @details All the data in the input queue is erased and lost, any waiting
+ * thread is resumed with status @p Q_RESET.
*
- * @param[in] qp pointer to a @p Queue structure
+ * @param[in] iqp pointer to an @p InputQueue structure
+ *
+ * @note A reset operation can be used by a low level driver in order to obtain
+ * immediate attention from the high level layers.
*/
-void chIQReset(Queue *qp) {
+void chIQResetI(InputQueue *iqp) {
- chSysLock();
-
- qp->q_rdptr = qp->q_wrptr = qp->q_buffer;
- chSemResetI(&qp->q_sem, 0);
-
- chSysUnlock();
+ iqp->q_rdptr = iqp->q_wrptr = iqp->q_buffer;
+ chSemResetI(&iqp->q_sem, 0);
}
/**
- * @brief Inserts a byte into an input queue.
+ * @brief Input queue write.
+ * @details A byte value is written into the low end of an input queue.
*
- * @param[in] qp pointer to a @p Queue structure
- * @param[in] b the byte value to be written
- * @retval Q_OK if the operation is successful.
- * @retval Q_FULL if the queue is full.
- * @note This function is the lower side endpoint of the Input Queue.
- * @note This function must be called with interrupts disabled or from an
- * interrupt handler.
+ * @param[in] iqp pointer to an @p InputQueue structure
+ * @param[in] b the byte value to be written in the queue
+ * @return The operation status, it can be one of:
+ * @retval Q_OK if the operation has been completed with success.
+ * @retval Q_FULL if the queue is full and the operation cannot be completed.
*/
-msg_t chIQPutI(Queue *qp, uint8_t b) {
+msg_t chIQPutI(InputQueue *iqp, uint8_t b) {
- if (chIQIsFull(qp))
+ if (chIQIsFull(iqp))
return Q_FULL;
- *qp->q_wrptr++ = b;
- if (qp->q_wrptr >= qp->q_top)
- qp->q_wrptr = qp->q_buffer;
- chSemSignalI(&qp->q_sem);
+ *iqp->q_wrptr++ = b;
+ if (iqp->q_wrptr >= iqp->q_top)
+ iqp->q_wrptr = iqp->q_buffer;
+ chSemSignalI(&iqp->q_sem);
return Q_OK;
}
/**
- * @brief Gets a byte from the input queue.
- * @details If the queue is empty then the calling thread is suspended until
- * a byte arrives in the queue.
+ * @brief Input queue read.
+ * @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.
*
- * @param[in] qp pointer to a @p Queue structure
- * @return A byte value from the queue.
+ * @param[in] iqp pointer to an @p InputQueue 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 or:
+ * @retval Q_TIMEOUT if the specified time expired.
* @retval Q_RESET if the queue was reset.
+ *
+ * @note The @p time parameter is only meaningful if the
+ * @p CH_USE_SEMAPHORES_TIMEOUT kernel option is activated,
+ * otherwise only the @p TIME_INFINITE value is accepted.
*/
-msg_t chIQGet(Queue *qp) {
+msg_t chIQGetTimeout(InputQueue *iqp, systime_t timeout) {
uint8_t b;
+ msg_t msg;
+#if CH_USE_SEMAPHORES_TIMEOUT
chSysLock();
-
- if (chSemWaitS(&qp->q_sem) < RDY_OK) {
-
+ if ((msg = chSemWaitTimeoutS(&iqp->q_sem, timeout)) < RDY_OK) {
chSysUnlock();
- return Q_RESET;
+ return msg;
}
- b = *qp->q_rdptr++;
- if (qp->q_rdptr >= qp->q_top)
- qp->q_rdptr = qp->q_buffer;
-
- if (qp->q_notify)
- qp->q_notify();
-
- chSysUnlock();
- return b;
-}
-
-#if CH_USE_QUEUES_TIMEOUT && CH_USE_SEMAPHORES_TIMEOUT
-/**
- * @brief Gets a byte from the input queue.
- * @details If the queue is empty then the calling thread is suspended until
- * a byte arrives in the queue or the specified time expires.
- *
- * @param[in] qp pointer to a @p Queue structure
- * @param[in] time the number of ticks before the operation timeouts
- * @return A byte value from the queue.
- * @retval Q_TIMEOUT if the specified time expired.
- * @retval Q_RESET if the queue was reset.
- * @note The function is available only if the @p CH_USE_QUEUES_TIMEOUT and
- * @p CH_USE_SEMAPHORES_TIMEOUT options are enabled in @p chconf.h.
- */
-msg_t chIQGetTimeout(Queue *qp, systime_t time) {
- uint8_t b;
- msg_t msg;
+#else
+ chDbgCheck(timeout == TIME_INFINITE, "chIQGetTimeout");
chSysLock();
-
- if ((msg = chSemWaitTimeoutS(&qp->q_sem, time)) < RDY_OK) {
-
+ if ((msg = chSemWaitS(&iqp->q_sem)) < RDY_OK) {
chSysUnlock();
return msg;
}
- b = *qp->q_rdptr++;
- if (qp->q_rdptr >= qp->q_top)
- qp->q_rdptr = qp->q_buffer;
+#endif
+ b = *iqp->q_rdptr++;
+ if (iqp->q_rdptr >= iqp->q_top)
+ iqp->q_rdptr = iqp->q_buffer;
- if (qp->q_notify)
- qp->q_notify();
+ if (iqp->q_notify)
+ iqp->q_notify();
chSysUnlock();
return b;
}
-#endif /* (CH_USE_QUEUES_TIMEOUT && CH_USE_SEMAPHORES_TIMEOUT */
/**
- * @brief Reads some data from the input queue into the specified buffer.
- * @details The function is non-blocking and can return zero if the queue is
+ * @brief Non-blocking read.
+ * @details The function reads data from an input queue into a buffer. The
+ * transfer is non-blocking and can return zero if the queue is
* empty.
*
- * @param[in] qp pointer to a @p Queue structure
- * @param[out] buffer the data buffer
- * @param[in] n the maximum amount of data to be read
- * @return The number of bytes read.
- * @note This function is the upper side endpoint of the input queue.
+ * @param[in] iqp pointer to an @p InputQueue structure
+ * @param[out] buffer pointer to the buffer where the input data is copied
+ * @param[in] n the maximum amount of data to be transferred
+ * @return The number of bytes transferred.
+ *
* @note The function is not atomic, if you need atomicity it is suggested
- * to use a semaphore for mutual exclusion.
+ * to use a semaphore or a mutex for mutual exclusion.
*/
-size_t chIQRead(Queue *qp, uint8_t *buffer, size_t n) {
-
+size_t chIQRead(InputQueue *iqp, uint8_t *buffer, size_t n) {
size_t r = 0;
+
while (n--) {
chSysLock();
-
- if (chIQIsEmpty(qp)) {
-
+ if (chIQIsEmpty(iqp)) {
chSysUnlock();
break;
}
- chSemFastWaitI(&qp->q_sem);
- *buffer++ = *qp->q_rdptr++;
- if (qp->q_rdptr >= qp->q_top)
- qp->q_rdptr = qp->q_buffer;
-
+ chSemFastWaitI(&iqp->q_sem);
+ *buffer++ = *iqp->q_rdptr++;
+ if (iqp->q_rdptr >= iqp->q_top)
+ iqp->q_rdptr = iqp->q_buffer;
chSysUnlock();
r++;
}
-
- if (r && qp->q_notify) {
+ if (r && iqp->q_notify) {
chSysLock();
-
- qp->q_notify();
-
+ iqp->q_notify();
chSysUnlock();
}
-
return r;
}
/**
* @brief Initializes an output queue.
- * @details A Semaphore is internally initialized and works as a counter of the
- * free bytes in the queue.
+ * @details A Semaphore is internally initialized and works as a counter of
+ * the free bytes in the queue.
*
- * @param[out] qp pointer to a @p Queue structure
+ * @param[out] oqp pointer to an @p OutputQueue structure
* @param[in] buffer pointer to a memory area allocated as queue buffer
* @param[in] size size of the queue buffer
* @param[in] onotify pointer to a callback function that is invoked when
- * some data is written in the Queue. The value can be
+ * some data is written to the queue. The value can be
* @p NULL.
+ *
+ * @note The callback is invoked from within the S-Locked system state,
+ * see @ref system_states.
*/
-void chOQInit(Queue *qp, uint8_t *buffer, size_t size, qnotify_t onotify) {
+void chOQInit(OutputQueue *oqp, uint8_t *buffer,
+ size_t size, qnotify_t onotify) {
- qp->q_buffer = qp->q_rdptr = qp->q_wrptr = buffer;
- qp->q_top = buffer + size;
- chSemInit(&qp->q_sem, size);
- qp->q_notify = onotify;
+ oqp->q_buffer = oqp->q_rdptr = oqp->q_wrptr = buffer;
+ oqp->q_top = buffer + size;
+ chSemInit(&oqp->q_sem, size);
+ oqp->q_notify = onotify;
}
/**
- * @brief Resets an Output Queue.
- * @details All the data is lost and the waiting threads resumed.
+ * @brief Resets an output queue.
+ * @details All the data in the output queue is erased and lost, any waiting
+ * thread is resumed with status @p Q_RESET.
*
- * @param[in] qp pointer to a @p Queue structure
+ * @param[in] oqp pointer to an @p OutputQueue structure
+ *
+ * @note A reset operation can be used by a low level driver in order to obtain
+ * immediate attention from the high level layers.
*/
-void chOQReset(Queue *qp) {
-
- chSysLock();
+void chOQResetI(OutputQueue *oqp) {
- qp->q_rdptr = qp->q_wrptr = qp->q_buffer;
- chSemResetI(&qp->q_sem, (cnt_t)(qp->q_top - qp->q_buffer));
-
- chSysUnlock();
+ oqp->q_rdptr = oqp->q_wrptr = oqp->q_buffer;
+ chSemResetI(&oqp->q_sem, (cnt_t)(oqp->q_top - oqp->q_buffer));
}
/**
- * @brief Inserts a byte in the output queue.
- * @details If the queue is full then the thread is suspended until the queue
- * has free space available.
+ * @brief Output queue write.
+ * @details This function writes a byte value to an output queue. If the queue
+ * is full then the calling thread is suspended until there is space
+ * in the queue or a timeout occurs.
*
- * @param[in] qp pointer to a @p Queue structure
- * @param[in] b the byte value to be written
+ * @param[in] oqp pointer to an @p OutputQueue 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 The operation status:
+ * @retval Q_OK if the operation succeeded.
+ * @retval Q_TIMEOUT if the specified time expired.
+ * @retval Q_RESET if the queue was reset.
+ *
+ * @note The @p time parameter is only meaningful if the
+ * @p CH_USE_SEMAPHORES_TIMEOUT kernel option is activated,
+ * otherwise only the @p TIME_INFINITE value is accepted.
*/
-void chOQPut(Queue *qp, uint8_t b) {
+msg_t chOQPutTimeout(OutputQueue *oqp, uint8_t b, systime_t timeout) {
+ msg_t msg;
+#if CH_USE_SEMAPHORES_TIMEOUT
chSysLock();
+ if ((msg = chSemWaitTimeoutS(&oqp->q_sem, timeout)) < RDY_OK) {
+ chSysUnlock();
+ return msg;
+ }
+#else
+ chDbgCheck(timeout == TIME_INFINITE, "chOQPutTimeout");
- chSemWaitS(&qp->q_sem);
- *qp->q_wrptr++ = b;
- if (qp->q_wrptr >= qp->q_top)
- qp->q_wrptr = qp->q_buffer;
+ chSysLock();
+ if ((msg = chSemWaitS(&oqp->q_sem)) < RDY_OK) {
+ chSysUnlock();
+ return msg;
+ }
+#endif
+ *oqp->q_wrptr++ = b;
+ if (oqp->q_wrptr >= oqp->q_top)
+ oqp->q_wrptr = oqp->q_buffer;
- if (qp->q_notify)
- qp->q_notify();
+ if (oqp->q_notify)
+ oqp->q_notify();
chSysUnlock();
+ return Q_OK;
}
/**
- * @brief Gets a byte from an output queue.
+ * @brief Output queue read.
+ * @details A byte value is read from the low end of an output queue.
*
- * @param[in] qp pointer to a @p Queue structure
- * @return The byte value from the queue.
+ * @param[in] oqp pointer to an @p OutputQueue structure
+ * @return The byte value from the queue or:
* @retval Q_EMPTY if the queue is empty.
- * @note This function is the lower side endpoint of the output queue.
- * @note This function must be called with interrupts disabled or from an
- * interrupt handler.
*/
-msg_t chOQGetI(Queue *qp) {
+msg_t chOQGetI(OutputQueue *oqp) {
uint8_t b;
- if (chOQIsEmpty(qp))
+ if (chOQIsEmpty(oqp))
return Q_EMPTY;
- b = *qp->q_rdptr++;
- if (qp->q_rdptr >= qp->q_top)
- qp->q_rdptr = qp->q_buffer;
- chSemSignalI(&qp->q_sem);
+ b = *oqp->q_rdptr++;
+ if (oqp->q_rdptr >= oqp->q_top)
+ oqp->q_rdptr = oqp->q_buffer;
+ chSemSignalI(&oqp->q_sem);
return b;
}
@@ -293,218 +302,43 @@ msg_t chOQGetI(Queue *qp) { * @note The function is not atomic, if you need atomicity it is suggested
* to use a semaphore for mutual exclusion.
*/
-size_t chOQWrite(Queue *qp, uint8_t *buffer, size_t n) {
+/**
+ * @brief Non-blocking write.
+ * @details The function writes data from a buffer to an output queue. The
+ * transfer is non-blocking and can return zero if the queue is
+ * already full.
+ *
+ * @param[in] oqp pointer to an @p OutputQueue structure
+ * @param[out] buffer pointer to the buffer where the output data is stored
+ * @param[in] n the maximum amount of data to be transferred
+ * @return The number of bytes transferred.
+ *
+ * @note The function is not atomic, if you need atomicity it is suggested
+ * to use a semaphore or a mutex for mutual exclusion.
+ */
+size_t chOQWrite(OutputQueue *oqp, uint8_t *buffer, size_t n) {
size_t w = 0;
while (n--) {
chSysLock();
-
- if (chOQIsFull(qp)) {
-
+ if (chOQIsFull(oqp)) {
chSysUnlock();
break;
}
- chSemFastWaitI(&qp->q_sem);
- *qp->q_wrptr++ = *buffer++;
- if (qp->q_wrptr >= qp->q_top)
- qp->q_wrptr = qp->q_buffer;
-
+ chSemFastWaitI(&oqp->q_sem);
+ *oqp->q_wrptr++ = *buffer++;
+ if (oqp->q_wrptr >= oqp->q_top)
+ oqp->q_wrptr = oqp->q_buffer;
chSysUnlock();
w++;
}
-
- if (w && qp->q_notify) {
+ if (w && oqp->q_notify) {
chSysLock();
-
- qp->q_notify();
-
+ oqp->q_notify();
chSysUnlock();
}
-
return w;
}
#endif /* CH_USE_QUEUES */
-#if CH_USE_QUEUES_HALFDUPLEX
- /**
- * @brief Initializes an half duplex queue.
- *
- * @param[out] qp pointer to the @p HalfDuplexQueue structure
- * @param[in] buffer pointer to a memory area allocated as buffer for the queue
- * @param[in] size the size of the queue buffer
- * @param[in] inotify pointer to a callback function that is invoked when
- * some data is read from the queue. The value can be
- * @p NULL.
- * @param[in] onotify pointer to a callback function that is invoked when
- * some data is written to the queue. The value can be
- * @p NULL.
- */
-void chHDQInit(HalfDuplexQueue *qp, uint8_t *buffer, size_t size,
- qnotify_t inotify, qnotify_t onotify) {
-
- qp->hdq_buffer = qp->hdq_rdptr = qp->hdq_wrptr = buffer;
- qp->hdq_top = buffer + size;
- chSemInit(&qp->hdq_isem, 0);
- chSemInit(&qp->hdq_osem, size);
- qp->hdq_inotify = inotify;
- qp->hdq_onotify = onotify;
-}
-
-/**
- * @brief Reads a byte from the receive queue.
- * @details If the queue is empty or is in transmission mode then the invoking
- * thread is suspended.
- *
- * @param[in] qp pointer to a @p HalfDuplexQueue structure
- * @return The byte value.
- * @retval Q_RESET if the queue was reset.
- */
-msg_t chHDQGetReceive(HalfDuplexQueue *qp) {
- uint8_t b;
-
- chSysLock();
-
- if (chSemWaitS(&qp->hdq_isem) < RDY_OK) {
-
- chSysUnlock();
- return Q_RESET;
- }
- /*
- * NOTE: The semaphore can be signaled only if the queue is in
- * receive mode.
- */
- b = *qp->hdq_rdptr++;
- if (qp->hdq_rdptr >= qp->hdq_top)
- qp->hdq_rdptr = qp->hdq_buffer;
-
- if (qp->hdq_inotify)
- qp->hdq_inotify();
-
- chSysUnlock();
- return b;
-}
-
-#if CH_USE_QUEUES_TIMEOUT && CH_USE_SEMAPHORES_TIMEOUT
-/**
- * @brief Reads a byte from the receive queue.
- * @details If the queue is empty or is in transmission mode then the invoking
- * thread is suspended.
- *
- * @param[in] qp pointer to a @p HalfDuplexQueue structure
- * @param[in] time the number of ticks before the operation timouts
- * @return The byte value.
- * @retval Q_TIMEOUT if a timeout occurs.
- * @note The function is available only if the @p CH_USE_QUEUES_TIMEOUT and
- * @p CH_USE_SEMAPHORES_TIMEOUT options are enabled in @p chconf.h.
- */
-msg_t chHDQGetReceiveTimeout(HalfDuplexQueue *qp, systime_t time) {
- uint8_t b;
- msg_t msg;
-
- chSysLock();
-
- if ((msg = chSemWaitTimeoutS(&qp->hdq_isem, time)) < RDY_OK) {
-
- chSysUnlock();
- return msg;
- }
- /*
- * NOTE: The semaphore can be signaled only if the queue is in
- * receive mode.
- */
- b = *qp->hdq_rdptr++;
- if (qp->hdq_rdptr >= qp->hdq_top)
- qp->hdq_rdptr = qp->hdq_buffer;
-
- if (qp->hdq_inotify)
- qp->hdq_inotify();
-
- chSysUnlock();
- return b;
-}
-#endif /* CH_USE_QUEUES_TIMEOUT && CH_USE_SEMAPHORES_TIMEOUT */
-
-/**
- * @brief Writes a byte into the transmit queue.
- * @details If the buffer contains unread input data then the the buffer is
- * cleared and the queue goes in transmission mode.
- *
- * @param[in] qp pointer to a @p HalfDuplexQueue structure
- * @param[in] b the byte value to be written
- */
-void chHDQPutTransmit(HalfDuplexQueue *qp, uint8_t b) {
-
- chSysLock();
-
- /*
- * Transmission mode requires that all the unread data must be destroyed.
- */
- if (qp->hdq_isem.s_cnt > 0) {
- qp->hdq_isem.s_cnt = 0;
- qp->hdq_rdptr = qp->hdq_wrptr = qp->hdq_buffer;
- }
-
- /*
- * Goes in transmission mode.
- */
- chSemWaitS(&qp->hdq_osem);
- *qp->hdq_wrptr++ = b;
- if (qp->hdq_wrptr >= qp->hdq_top)
- qp->hdq_wrptr = qp->hdq_buffer;
-
- if (qp->hdq_onotify)
- qp->hdq_onotify();
-
- chSysUnlock();
-}
-
-/**
- * @brief Gets a byte from the transmit queue.
- *
- * @param[in] qp pointer to a @p HalfDuplexQueue structure
- * @return The byte value.
- * @retval Q_EMPTY if the transmit queue is empty (not in transmission mode).
- * @note This function must be called with interrupts disabled or from an
- * interrupt handler.
- */
-msg_t chHDQGetTransmitI(HalfDuplexQueue *qp) {
- uint8_t b;
-
- if (!chHDQIsTransmitting(qp))
- return Q_EMPTY;
-
- b = *qp->hdq_rdptr++;
- if (qp->hdq_rdptr >= qp->hdq_top)
- qp->hdq_rdptr = qp->hdq_buffer;
- chSemSignalI(&qp->hdq_osem);
- return b;
-}
-
-/**
- * @brief Writes a byte into the receive queue.
- * @details If the queue is in transmission mode then the byte is lost.
- *
- * @param[in] qp pointer to a @p HalfDuplexQueue structure
- * @param[in] b the byte value to be written
- * @retval Q_OK if the operation is successful.
- * @retval Q_FULL if the driver is in transmit mode or the receive queue is full.
- * @note This function must be called with interrupts disabled or from an
- * interrupt handler.
- */
-msg_t chHDQPutReceiveI(HalfDuplexQueue *qp, uint8_t b) {
-
- if (chHDQIsTransmitting(qp))
- return Q_FULL;
-
- if (chHDQIsFullReceive(qp))
- return Q_FULL;
-
- *qp->hdq_wrptr++ = b;
- if (qp->hdq_wrptr >= qp->hdq_top)
- qp->hdq_wrptr = qp->hdq_buffer;
- chSemSignalI(&qp->hdq_isem);
- return Q_OK;
-}
-#endif /* CH_USE_QUEUES_HALFDUPLEX */
-
/** @} */
diff --git a/src/chserial.c b/src/chserial.c index 725df207d..bb2d7b7d7 100644 --- a/src/chserial.c +++ b/src/chserial.c @@ -123,96 +123,4 @@ dflags_t chFDDGetAndClearFlags(FullDuplexDriver *sd) { }
#endif /* CH_USE_SERIAL_FULLDUPLEX */
-#if CH_USE_SERIAL_HALFDUPLEX
-/**
- * @brief Initializes a generic half duplex driver.
- * @details The HW dependent part of the initialization has to be performed
- * outside, usually in the hardware initialization code.
- *
- * @param[out] sd pointer to a @p HalfDuplexDriver structure
- * @param[in] b pointer to a memory area allocated for the queue buffer
- * @param[in] size the buffer size
- * @param[in] inotify pointer to a callback function that is invoked when
- * some data is read from the queue. The value can be
- * @p NULL.
- * @param[in] onotify pointer to a callback function that is invoked when
- * some data is written in the queue. The value can be
- * @p NULL.
- */
-void chHDDInit(HalfDuplexDriver *sd, uint8_t *b, size_t size,
- qnotify_t inotify, qnotify_t onotify) {
-
- chDbgCheck((sd != NULL) && (b != NULL) && (size > 0), "chHDDInit");
-
- chHDQInit(&sd->sd_queue, b, size, inotify, onotify);
- chEvtInit(&sd->sd_ievent);
- chEvtInit(&sd->sd_oevent);
- chEvtInit(&sd->sd_sevent);
- sd->sd_flags = SD_NO_ERROR;
-}
-
-/**
- * @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.
- * @param[in] sd pointer to a @p FullDuplexDriver structure
- * @param[in] b the byte to be written in the driver's input queue
- */
-void chHDDIncomingDataI(HalfDuplexDriver *sd, uint8_t b) {
-
- if (chHDQPutReceiveI(&sd->sd_queue, b) < Q_OK)
- chHDDAddFlagsI(sd, SD_OVERRUN_ERROR);
- else
- chEvtBroadcastI(&sd->sd_ievent);
-}
-
-/**
- * @brief Handles outgoing data.
- * @details Must be called from the output interrupt service routine in order
- * to get the next byte to be transmitted.
- *
- * @param[in] sd pointer to a @p HalfDuplexDriver structure
- * @return The byte value read from the driver's output queue.
- * @retval Q_EMPTY if the queue is empty (the lower driver usually disables
- * the interrupt source when this happens).
- */
-msg_t chHDDRequestDataI(HalfDuplexDriver *sd) {
-
- msg_t b = chHDQGetTransmitI(&sd->sd_queue);
- if (b < Q_OK)
- chEvtBroadcastI(&sd->sd_oevent);
- return b;
-}
-
-/**
- * @brief Handles communication events/errors.
- * @details Must be called from the I/O interrupt service routine in order to
- * notify I/O conditions as errors, signals change etc.
- *
- * @param[in] sd pointer to a @p HalfDuplexDriver structure
- * @param[in] mask condition flags to be added to the mask
- */
-void chHDDAddFlagsI(HalfDuplexDriver *sd, dflags_t mask) {
-
- sd->sd_flags |= mask;
- chEvtBroadcastI(&sd->sd_sevent);
-}
-
-/**
- * @brief Returns and clears the errors mask associated to the driver.
- *
- * @param[in] sd pointer to a @p HalfDuplexDriver structure
- * @return The condition flags modified since last time this function was
- * invoked.
- */
-dflags_t chHDDGetAndClearFlags(HalfDuplexDriver *sd) {
- dflags_t mask;
-
- mask = sd->sd_flags;
- sd->sd_flags = SD_NO_ERROR;
- return mask;
-}
-#endif /* CH_USE_SERIAL_HALFDUPLEX */
-
/** @} */
diff --git a/src/include/queues.h b/src/include/queues.h index eea80e804..ca587d388 100644 --- a/src/include/queues.h +++ b/src/include/queues.h @@ -43,9 +43,13 @@ typedef void (*qnotify_t)(void); #if CH_USE_QUEUES /** - * @brief I/O queue structure. - * @details This structure is used by both Input and Output Queues, - * the difference is on how the semaphore is initialized. + * @brief Generic I/O queue structure. + * @details This structure represents a generic Input or Output asymmetrical + * queue. The queue is asymmetrical because one end is meant to be + * accessed from a thread context, and thus can be blocking, the other + * end is accessible from interrupt handlers or from within a kernel + * lock zone (see <b>I-Locked</b> and <b>S-Locked</b> states in + * @ref system_states) and is non-blocking. */ typedef struct { uint8_t *q_buffer; /**< Pointer to the queue buffer.*/ @@ -55,7 +59,7 @@ typedef struct { uint8_t *q_rdptr; /**< Read pointer.*/ Semaphore q_sem; /**< Counter @p Semaphore.*/ qnotify_t q_notify; /**< Data notification callback.*/ -} Queue; +} GenericQueue; /** Returns the queue's buffer size. */ #define chQSize(q) ((q)->q_top - (q)->q_buffer) @@ -68,109 +72,85 @@ typedef struct { */ #define chQSpace(q) chSemGetCounterI(&(q)->q_sem) -/** Evaluates to TRUE if the specified Input Queue is empty. */ -#define chIQIsEmpty(q) (chQSpace(q) <= 0) - -/** Evaluates to TRUE if the specified Input Queue is full. */ -#define chIQIsFull(q) (chQSpace(q) >= chQSize(q)) - -/** Evaluates to TRUE if the specified Output Queue is empty. */ -#define chOQIsEmpty(q) (chQSpace(q) >= chQSize(q)) - -/** Evaluates to TRUE if the specified Output Queue is full. */ -#define chOQIsFull(q) (chQSpace(q) <= 0) - -#ifdef __cplusplus -extern "C" { -#endif - /* - * Input Queues functions. An Input Queue is usually written into by an - * interrupt handler and read from a thread. - */ - void chIQInit(Queue *qp, uint8_t *buffer, size_t size, qnotify_t inotify); - void chIQReset(Queue *qp); - msg_t chIQPutI(Queue *qp, uint8_t b); - msg_t chIQGet(Queue *qp); - size_t chIQRead(Queue *qp, uint8_t *buffer, size_t n); -#if CH_USE_QUEUES_TIMEOUT - msg_t chIQGetTimeout(Queue *qp, systime_t time); -#endif - - /* - * Output Queues functions. An Output Queue is usually written into by a - * thread and read from an interrupt handler. - */ - void chOQInit(Queue *queue, uint8_t *buffer, size_t size, qnotify_t onotify); - void chOQReset(Queue *queue); - void chOQPut(Queue *queue, uint8_t b); - msg_t chOQGetI(Queue *queue); - size_t chOQWrite(Queue *queue, uint8_t *buffer, size_t n); -#ifdef __cplusplus -} -#endif -#endif /* CH_USE_QUEUES */ - -#if CH_USE_QUEUES_HALFDUPLEX /** - * @brief Half duplex queue structure. + * @brief Input queue structure. + * @details This structure represents a generic asymmetrical input queue. + * Writing in the queue is non-blocking and can be performed from + * interrupt handlers or from within a kernel lock zone (see + * <b>I-Locked</b> and <b>S-Locked</b> states in @ref system_states). + * Reading the queue can be a blocking operation and is supposed to + * be performed by a system thread. + * @extends GenericQueue */ -typedef struct { - uint8_t *hdq_buffer; /**< Pointer to the queue buffer.*/ - uint8_t *hdq_top; /**< Pointer to the first location - after the buffer. */ - uint8_t *hdq_wrptr; /**< Write pointer.*/ - uint8_t *hdq_rdptr; /**< Read pointer.*/ - Semaphore hdq_isem; /**< Input counter @p Semaphore.*/ - Semaphore hdq_osem; /**< Output counter @p Semaphore.*/ - qnotify_t hdq_inotify; /**< Input data notification - callback.*/ - qnotify_t hdq_onotify; /**< Output data notification - callback.*/ -} HalfDuplexQueue; +typedef GenericQueue InputQueue; -/** Returns the queue's buffer size. */ -#define chHDQSize(q) ((q)->hdq_top - (q)->hdq_buffer) +/** Evaluates to @p TRUE if the specified Input Queue is empty. */ +#define chIQIsEmpty(q) (chQSpace(q) <= 0) + +/** Evaluates to @p TRUE if the specified Input Queue is full. */ +#define chIQIsFull(q) (chQSpace(q) >= chQSize(q)) /** - * Returns the queue space when in transmission mode. - * @note The returned value can be less than zero when there are waiting - * threads on the internal semaphore. + * @brief Input queue read. + * @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. + * + * @param[in] iqp pointer to an @p InputQueue structure + * @return A byte value from the queue or: + * @retval Q_RESET if the queue was reset. */ -#define chHDQEmptySpace(q) chSemGetCounterI(&(q)->hdq_osem) +#define chIQGet(iqp) chIQGetTimeout(iqp, TIME_INFINITE) /** - * Returns the number of the bytes in the queue when in receive mode. - * @note The returned value can be less than zero when there are waiting - * threads on the internal semaphore. + * @brief Output queue structure. + * @details This structure represents a generic asymmetrical output queue. + * Reading from the queue is non-blocking and can be performed from + * interrupt handlers or from within a kernel lock zone (see + * <b>I-Locked</b> and <b>S-Locked</b> states in @ref system_states). + * Writing the queue can be a blocking operation and is supposed to + * be performed by a system thread. + * @extends GenericQueue */ -#define chHDQFilledSpace(q) chSemGetCounterI(&(q)->hdq_isem) +typedef GenericQueue OutputQueue; -/** Evaluates to TRUE if the queue is in transmit mode. */ -#define chHDQIsTransmitting(q) (chHDQEmptySpace(q) < chHDQSize(q)) +/** Evaluates to @p TRUE if the specified Output Queue is empty. */ +#define chOQIsEmpty(q) (chQSpace(q) >= chQSize(q)) -/** Evaluates to TRUE if the queue is in receive mode. */ -#define chHDQIsReceiving(q) (chHDQEmptySpaceQ(q) >= chHDQSize(q)) +/** Evaluates to @p TRUE if the specified Output Queue is full. */ +#define chOQIsFull(q) (chQSpace(q) <= 0) -/** Evaluates to TRUE if the receive queue is full. */ -#define chHDQIsFullReceive(q) (chHDQFilledSpace(q) >= chHDQSize(q)) +/** + * @brief Output queue write. + * @details This function writes a byte value to an output queue. If the queue + * is full then the calling thread is suspended until there is space + * in the queue. + * + * @param[in] oqp pointer to an @p OutputQueue structure + * @param[in] b the byte value to be written in the queue + * @return The operation status: + * @retval Q_OK if the operation succeeded. + * @retval Q_RESET if the queue was reset. + */ +#define chOQPut(oqp, b) chOQPutTimeout(oqp, b, TIME_INFINITE) #ifdef __cplusplus extern "C" { #endif - void chHDQInit(HalfDuplexQueue *qp, uint8_t *buffer, size_t size, - qnotify_t inotify, qnotify_t onotify); - msg_t chHDQGetReceive(HalfDuplexQueue *qp); - void chHDQPutTransmit(HalfDuplexQueue *qp, uint8_t b); - msg_t chHDQGetTransmitI(HalfDuplexQueue *qp); - msg_t chHDQPutReceiveI(HalfDuplexQueue *qp, uint8_t b); -#if CH_USE_QUEUES_TIMEOUT - msg_t chHDQGetReceiveTimeout(HalfDuplexQueue *qp, systime_t time); -#endif + void chIQInit(InputQueue *qp, uint8_t *buffer, size_t size, qnotify_t inotify); + void chIQResetI(InputQueue *qp); + msg_t chIQPutI(InputQueue *qp, uint8_t b); + msg_t chIQGetTimeout(InputQueue *qp, systime_t timeout); + size_t chIQRead(InputQueue *qp, uint8_t *buffer, size_t n); + void chOQInit(OutputQueue *queue, uint8_t *buffer, size_t size, qnotify_t onotify); + void chOQResetI(OutputQueue *queue); + msg_t chOQPutTimeout(OutputQueue *queue, uint8_t b, systime_t timeout); + msg_t chOQGetI(OutputQueue *queue); + size_t chOQWrite(OutputQueue *queue, uint8_t *buffer, size_t n); #ifdef __cplusplus } #endif - -#endif /* CH_USE_QUEUES_HALFDUPLEX */ +#endif /* CH_USE_QUEUES */ #endif /* _QUEUES_H_ */ diff --git a/src/include/serial.h b/src/include/serial.h index ebb3392bb..6530fae0d 100644 --- a/src/include/serial.h +++ b/src/include/serial.h @@ -54,14 +54,14 @@ typedef struct { /** Input queue. Incoming data can be read from this queue by using the
* queues APIs.*/
- Queue sd_iqueue;
+ InputQueue sd_iqueue;
/** Data Available @p EventSource. This event is generated when some incoming
* data is inserted in the Input @p Queue.*/
EventSource sd_ievent;
/** Output queue. Outgoing data can be written to this Output @p Queue by
* using the queues APIs.*/
- Queue sd_oqueue;
+ OutputQueue sd_oqueue;
/** Data Transmitted @p EventSource. This event is generated when the
* Output @p Queue is empty.*/
EventSource sd_oevent;
@@ -110,58 +110,6 @@ extern "C" { #endif /* CH_USE_SERIAL_FULLDUPLEX */
-#if CH_USE_SERIAL_HALFDUPLEX
-
-/**
- * @brief Full Duplex Serial Driver main structure.
- */
-typedef struct {
-
- /** Data queue. Transmit/receive @p HalfDuplexQueue.*/
- HalfDuplexQueue sd_queue;
- /** Data Available @p EventSource. This event is generated when some
- * incoming data is inserted in the receive queue.*/
- EventSource sd_ievent;
- /** Data Transmitted @p EventSource. This event is generated when the
- * transmission queue is empty and the driver can either transmit more
- * data or enter receive mode.*/
- EventSource sd_oevent;
- /** I/O driver status flags. This field should not be read directly but
- * the @p chHDDGetAndClearFlags() funtion should be used
- * instead.*/
- dflags_t sd_flags;
- /** Status Change Event Source. This event is generated when a condition
- * flag was changed.*/
- EventSource sd_sevent;
-} HalfDuplexDriver;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
- void chHDDInit(HalfDuplexDriver *sd, uint8_t *b, size_t size,
- qnotify_t inotify, qnotify_t onotify);
- void chHDDIncomingDataI(HalfDuplexDriver *sd, uint8_t b);
- msg_t chHDDRequestDataI(HalfDuplexDriver *sd);
- void chHDDAddFlagsI(HalfDuplexDriver *sd, dflags_t mask);
- dflags_t chHDDGetAndClearFlags(HalfDuplexDriver *sd);
-#ifdef __cplusplus
-}
-#endif
-
-/** @see chHDQGetReceive()*/
-#define chHDDGetReceive(sd) \
- chHDQGetReceive(&(sd)->sd_queue)
-
-/** @see chHDQGetReceiveTimeout()*/
-#define chHDDGetReceiveTimeout(sd, t) \
- chHDQGetReceiveTimeout(&(sd)->sd_queue, t)
-
-/** @see chHDQPutTransmit()*/
-#define chHDDPutTransmit(sd, b) \
- chHDQPutTransmit(&(sd)->sd_queue, b)
-
-#endif /* CH_USE_SERIAL_HALFDUPLEX */
-
#endif /* _SERIAL_H_ */
/** @} */
|