Input buffers queues code finished.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@8624 35acf78f-673a-0410-8e92-d51de3d6d3f4
master
Giovanni Di Sirio 2015-12-20 11:38:54 +00:00
parent 0fcf05cf4c
commit 59dfc570f2
2 changed files with 72 additions and 18 deletions

View File

@ -187,6 +187,13 @@ extern "C" {
void ibqObjectInit(io_buffers_queue_t *ibqp, uint8_t *bp, void ibqObjectInit(io_buffers_queue_t *ibqp, uint8_t *bp,
size_t size, size_t n, size_t size, size_t n,
dbnotify_t infy, void *link); dbnotify_t infy, void *link);
uint8_t *ibqGetEmptyBufferI(input_buffers_queue_t *ibqp);
void ibqPostBufferI(input_buffers_queue_t *ibqp, size_t size);
msg_t ibqGetDataTimeoutI(input_buffers_queue_t *ibqp, systime_t timeout);
void ibqReleaseDataI(input_buffers_queue_t *ibqp);
msg_t ibqGetTimeout(input_buffers_queue_t *ibqp, systime_t timeout);
size_t ibqReadTimeout(input_buffers_queue_t *ibqp, uint8_t *bp,
size_t n, systime_t timeout);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -22,6 +22,8 @@
* @{ * @{
*/ */
#include <string.h>
#include "hal.h" #include "hal.h"
/*===========================================================================*/ /*===========================================================================*/
@ -105,7 +107,7 @@ uint8_t *ibqGetEmptyBufferI(input_buffers_queue_t *ibqp) {
* *
* @iclass * @iclass
*/ */
void ibqPostBufferI(io_buffers_queue_t *ibqp, size_t size) { void ibqPostBufferI(input_buffers_queue_t *ibqp, size_t size) {
osalDbgCheckClassI(); osalDbgCheckClassI();
osalDbgAssert(!ibqIsFullI(ibqp), "buffers queue full"); osalDbgAssert(!ibqIsFullI(ibqp), "buffers queue full");
@ -125,8 +127,8 @@ void ibqPostBufferI(io_buffers_queue_t *ibqp, size_t size) {
} }
/** /**
* @brief Gets the next filled buffer from the queue. * @brief Gets the next data-filled buffer from the queue.
* @note The function always returns the same buffer if called repeatedly. * @note The function always acquires the same buffer if called repeatedly.
* @post After calling the function the fields @p ptr and @p top are set * @post After calling the function the fields @p ptr and @p top are set
* at beginning and end of the buffer data or @NULL if the queue * at beginning and end of the buffer data or @NULL if the queue
* is empty. * is empty.
@ -137,27 +139,25 @@ void ibqPostBufferI(io_buffers_queue_t *ibqp, size_t size) {
* - @a TIME_IMMEDIATE immediate timeout. * - @a TIME_IMMEDIATE immediate timeout.
* - @a TIME_INFINITE no timeout. * - @a TIME_INFINITE no timeout.
* . * .
* @return A pointer to filled buffer area. * @return The operation status.
* @retval MSG_OK if a buffer has been acquired. * @retval MSG_OK if a buffer has been acquired.
* @retval MSG_TIMEOUT if the specified time expired. * @retval MSG_TIMEOUT if the specified time expired.
* @retval MSG_RESET if the queue has been reset. * @retval MSG_RESET if the queue has been reset.
* *
* @iclass * @iclass
*/ */
msg_t ibqGetFullBufferTimeoutI(input_buffers_queue_t *ibqp, msg_t ibqGetDataTimeoutI(input_buffers_queue_t *ibqp, systime_t timeout) {
systime_t timeout) {
osalDbgCheckClassI(); osalDbgCheckClassI();
while (ibqIsEmptyI(ibqp)) { while (ibqIsEmptyI(ibqp)) {
msg_t msg = osalThreadEnqueueTimeoutS(&ibqp->waiting, timeout); msg_t msg = osalThreadEnqueueTimeoutS(&ibqp->waiting, timeout);
if (msg < Q_OK) { if (msg < Q_OK) {
ibqp->ptr = NULL;
return msg; return msg;
} }
} }
/* Buffer boundaries.*/ /* Setting up the "current" buffer and its boundary.*/
ibqp->ptr = ibqp->brdptr + sizeof (size_t); ibqp->ptr = ibqp->brdptr + sizeof (size_t);
ibqp->top = ibqp->ptr + *((size_t *)ibqp->brdptr); ibqp->top = ibqp->ptr + *((size_t *)ibqp->brdptr);
@ -165,13 +165,14 @@ msg_t ibqGetFullBufferTimeoutI(input_buffers_queue_t *ibqp,
} }
/** /**
* @brief Releases the next filled buffer back in the queue. * @brief Releases the data buffer back in the queue.
* @note The object callback is called after releasing the buffer.
* *
* @param[out] ibqp pointer to the @p input_buffers_queue_t object * @param[out] ibqp pointer to the @p input_buffers_queue_t object
* *
* @iclass * @iclass
*/ */
void ibqReleaseBufferI(io_buffers_queue_t *ibqp) { void ibqReleaseDataI(input_buffers_queue_t *ibqp) {
osalDbgCheckClassI(); osalDbgCheckClassI();
osalDbgAssert(!ibqIsEmptyI(ibqp), "buffers queue empty"); osalDbgAssert(!ibqIsEmptyI(ibqp), "buffers queue empty");
@ -183,7 +184,7 @@ void ibqReleaseBufferI(io_buffers_queue_t *ibqp) {
ibqp->brdptr = ibqp->buffers; ibqp->brdptr = ibqp->buffers;
} }
/* Marked as no more sequentially accessible.*/ /* No "current" buffer.*/
ibqp->ptr = NULL; ibqp->ptr = NULL;
/* Notifying the buffer release.*/ /* Notifying the buffer release.*/
@ -197,8 +198,6 @@ void ibqReleaseBufferI(io_buffers_queue_t *ibqp) {
* @details This function reads a byte value from an input queue. If * @details This function reads a byte value from an input queue. If
* the queue is empty then the calling thread is suspended until a * the queue is empty then the calling thread is suspended until a
* new buffer arrives in the queue or a timeout occurs. * new buffer arrives in the queue or a timeout occurs.
* @note The callback is invoked before reading the character from the
* buffer or before entering the suspended state.
* *
* @param[in] ibqp pointer to the @p input_buffers_queue_t object * @param[in] ibqp pointer to the @p input_buffers_queue_t object
* @param[in] timeout the number of ticks before the operation timeouts, * @param[in] timeout the number of ticks before the operation timeouts,
@ -217,7 +216,7 @@ msg_t ibqGetTimeout(input_buffers_queue_t *ibqp, systime_t timeout) {
/* This condition indicates that a new buffer must be acquired.*/ /* This condition indicates that a new buffer must be acquired.*/
if (ibqp->ptr == NULL) { if (ibqp->ptr == NULL) {
msg = ibqGetFullBufferTimeoutI(ibqp, timeout); msg = ibqGetDataTimeoutI(ibqp, timeout);
if (msg != MSG_OK) { if (msg != MSG_OK) {
return msg; return msg;
} }
@ -229,8 +228,8 @@ msg_t ibqGetTimeout(input_buffers_queue_t *ibqp, systime_t timeout) {
/* If the current buffer has been fully read then it is returned as /* If the current buffer has been fully read then it is returned as
empty in the queue.*/ empty in the queue.*/
if (ibqp->ptr == ibqp->top) { if (ibqp->ptr >= ibqp->top) {
ibqReleaseBufferI(ibqp); ibqReleaseDataI(ibqp);
} }
return msg; return msg;
@ -244,8 +243,6 @@ msg_t ibqGetTimeout(input_buffers_queue_t *ibqp, systime_t timeout) {
* been reset. * been reset.
* @note The function is not atomic, if you need atomicity it is suggested * @note The function is not atomic, if you need atomicity it is suggested
* to use a semaphore or a mutex for mutual exclusion. * 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] ibqp pointer to the @p input_buffers_queue_t object * @param[in] ibqp pointer to the @p input_buffers_queue_t object
* @param[out] bp pointer to the data buffer * @param[out] bp pointer to the data buffer
@ -262,7 +259,57 @@ msg_t ibqGetTimeout(input_buffers_queue_t *ibqp, systime_t timeout) {
*/ */
size_t ibqReadTimeout(input_buffers_queue_t *ibqp, uint8_t *bp, size_t ibqReadTimeout(input_buffers_queue_t *ibqp, uint8_t *bp,
size_t n, systime_t timeout) { size_t n, systime_t timeout) {
size_t r = 0;
systime_t deadline;
osalSysLock();
/* Time window for the whole operation.*/
deadline = osalOsGetSystemTimeX() + timeout;
while (r < n) {
size_t size;
/* This condition indicates that a new buffer must be acquired.*/
if (ibqp->ptr == NULL) {
systime_t next_timeout = deadline - osalOsGetSystemTimeX();
/* Handling the case where the system time went past the deadline,
in this case next becomes a very high number because the system
time is an unsigned type.*/
if (next_timeout > timeout)
return MSG_TIMEOUT;
msg_t msg = ibqGetDataTimeoutI(ibqp, next_timeout);
if (msg != MSG_OK) {
return msg;
}
}
/* Size of the data chunk present in the current buffer.*/
size = ibqp->top - ibqp->ptr;
if (size > n - r) {
size = n - r;
}
/* Copying the chunk into the read buffer, the operation is performed
outside the critical zone.*/
osalSysUnlock();
memcpy(bp, ibqp->ptr, size);
osalSysLock();
/* Updating the pointers.*/
bp += size;
ibqp->ptr += size;
/* Has the current data buffer been finished? if so then release it.*/
if (ibqp->ptr >= ibqp->top) {
ibqReleaseDataI(ibqp);
}
}
osalSysUnlock();
return r;
} }
/** @} */ /** @} */