From ddcc89f8d136acd94bba873c2e851a5d2f50e67c Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Sun, 20 Dec 2015 09:45:43 +0000 Subject: [PATCH] git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@8619 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/hal_buffers.h | 131 +++++++++++++++++++++----------- os/hal/include/hal_queues.h | 38 +++++----- os/hal/src/hal_buffers.c | 141 +++++++++++++++++++++++++++++------ os/rt/include/chqueues.h | 14 ++-- 4 files changed, 229 insertions(+), 95 deletions(-) diff --git a/os/hal/include/hal_buffers.h b/os/hal/include/hal_buffers.h index 02f21f5cd..0acf9ebd9 100644 --- a/os/hal/include/hal_buffers.h +++ b/os/hal/include/hal_buffers.h @@ -29,8 +29,6 @@ /* Driver constants. */ /*===========================================================================*/ -#define HAL_BUFFERS_QUEUE_SIZE 2 - /*===========================================================================*/ /* Driver pre-compile time settings. */ /*===========================================================================*/ @@ -44,44 +42,21 @@ /*===========================================================================*/ /** - * @brief Type of an I/O buffer. + * @brief Type of a generic queue of buffers. */ -typedef struct hal_buffer io_buffer_t; - -/** - * @brief Structure of a generic buffer. - */ -struct hal_buffer { - /** - * @brief Pointer to the buffer in memory. - */ - uint8_t *buffer; - /** - * @brief Pointer to the first non-used location in the buffer. - */ - uint8_t *limit; - /** - * @brief Pointer to the buffer boundary. - */ - uint8_t *top; -}; - -/** - * @brief Type of a generic double buffer. - */ -typedef struct io_double_buffer io_double_buffer_t; +typedef struct io_buffers_queue io_buffers_queue_t; /** * @brief Double buffer notification callback type. * - * @param[in] iodbp the double buffer pointer + * @param[in] iodbp the buffers queue pointer */ -typedef void (*dbnotify_t)(io_double_buffer_t *iodbp); +typedef void (*dbnotify_t)(io_buffers_queue_t *bqp); /** - * @brief Structure of a generic double buffer. + * @brief Structure of a generic buffers queue. */ -struct io_double_buffer { +struct io_buffers_queue { /** * @brief Queue of waiting threads. */ @@ -89,23 +64,38 @@ struct io_double_buffer { /** * @brief Active buffers counter. */ - volatile size_t counter; + volatile size_t bcounter; /** * @brief Buffer write pointer. */ - io_buffer_t *bwrptr; + uint8_t *bwrptr; /** * @brief Buffer read pointer. */ - io_buffer_t *brdptr; + uint8_t *brdptr; + /** + * @brief Pointer to the buffers boundary. + */ + uint8_t *btop; + /** + * @brief Size of buffers. + * @note The buffer size must be not lower than sizeof(size_t) + 2 + * because the first bytes are used to store the used size of the + * buffer. + */ + size_t bsize; + /** + * @brief Number of buffers. + */ + size_t bn; + /** + * @brief Queue of buffer objects. + */ + uint8_t *buffers; /** * @brief Pointer for R/W sequential access. */ uint8_t *ptr; - /** - * @brief Queue of buffer objects. - */ - io_buffer_t buffers[HAL_BUFFERS_QUEUE_SIZE]; /** * @brief Data notification callback. */ @@ -117,19 +107,71 @@ struct io_double_buffer { }; /** - * @brief Type of an input double buffer. + * @brief Type of an input buffers queue. */ -typedef io_double_buffer_t input_double_buffer_t; +typedef io_buffers_queue_t input_buffers_queue_t; /** - * @brief Type of an output double buffer. + * @brief Type of an output buffers queue. */ -typedef io_double_buffer_t output_double_buffer_t; +typedef io_buffers_queue_t output_buffers_queue_t; /*===========================================================================*/ /* Driver macros. */ /*===========================================================================*/ +/** + * @name Macro Functions + * @{ + */ +/** + * @brief Returns the queue's number of buffers. + * + * @param[in] bqp pointer to an @p io_buffers_queue_t structure + * @return The number of buffers. + * + * @xclass + */ +#define bqSizeX(bqp) ((bqp)->bn) + +/** + * @brief Return the ready buffers number. + * @details Returns the number of filled buffers if used on an input queue + * or the number of empty buffers if used on an output queue. + * + * @param[in] bqp pointer to an @p io_buffers_queue_t structure + * @return The number of ready buffers. + * + * @iclass + */ +#define bqSpaceI(bqp) ((bqp)->bcounter) + +/** + * @brief Evaluates to @p TRUE if the specified input buffered queue is empty. + * + * @param[in] ibqp pointer to an @p input_buffers_queue_t structure + * @return The queue status. + * @retval false if the queue is not empty. + * @retval true if the queue is empty. + * + * @iclass + */ +#define iqbIsEmptyI(ibqp) ((bool)(bqSpaceI(ibqp) == 0U)) + +/** + * @brief Evaluates to @p TRUE if the specified input buffered queue is full. + * + * @param[in] ibqp pointer to an @p input_buffers_queue_t structure + * @return The queue status. + * @retval false if the queue is not full. + * @retval true if the queue is full. + * + * @iclass + */ +#define ibqIsFullI(ibqp) ((bool)(((ibqp)->bwrptr == (ibqp)->brdptr) && \ + ((ibqp)->bcounter != 0U))) +/** @} */ + /*===========================================================================*/ /* External declarations. */ /*===========================================================================*/ @@ -137,9 +179,8 @@ typedef io_double_buffer_t output_double_buffer_t; #ifdef __cplusplus extern "C" { #endif - void iobInit(io_buffer_t *iobp, uint8_t *bp, size_t size); - void idbObjectInit(input_double_buffer_t *idbp, - uint8_t *b1p, uint8_t *b2p, size_t size, + void ibqObjectInit(io_buffers_queue_t *ibqp, uint8_t *bp, + size_t size, size_t n, dbnotify_t infy, void *link); #ifdef __cplusplus } diff --git a/os/hal/include/hal_queues.h b/os/hal/include/hal_queues.h index da76aac8f..a2149f9fe 100644 --- a/os/hal/include/hal_queues.h +++ b/os/hal/include/hal_queues.h @@ -80,7 +80,7 @@ struct io_queue { /** * @brief Returns the queue's buffer size. * - * @param[in] qp pointer to a @p io_queue_t structure. + * @param[in] qp pointer to a @p io_queue_t structure * @return The buffer size. * * @xclass @@ -95,7 +95,7 @@ struct io_queue { * @details Returns the used space if used on an input queue or the empty * space if used on an output queue. * - * @param[in] qp pointer to a @p io_queue_t structure. + * @param[in] qp pointer to a @p io_queue_t structure * @return The buffer space. * * @iclass @@ -106,7 +106,7 @@ struct io_queue { * @brief Returns the queue application-defined link. * @note This function can be called in any context. * - * @param[in] qp pointer to a @p io_queue_t structure. + * @param[in] qp pointer to a @p io_queue_t structure * @return The application-defined link. * * @special @@ -153,24 +153,24 @@ typedef io_queue_t input_queue_t; #define iqGetEmptyI(iqp) (qSizeX(iqp) - qSpaceI(iqp)) /** - * @brief Evaluates to @p TRUE if the specified input queue is empty. + * @brief Evaluates to @p true if the specified input queue is empty. * - * @param[in] iqp pointer to an @p input_queue_t structure. + * @param[in] iqp pointer to an @p input_queue_t structure * @return The queue status. - * @retval FALSE if the queue is not empty. - * @retval TRUE if the queue is empty. + * @retval false if the queue is not empty. + * @retval true if the queue is empty. * * @iclass */ #define iqIsEmptyI(iqp) ((bool)(qSpaceI(iqp) == 0U)) /** - * @brief Evaluates to @p TRUE if the specified input queue is full. + * @brief Evaluates to @p true if the specified input queue is full. * - * @param[in] iqp pointer to an @p input_queue_t structure. + * @param[in] iqp pointer to an @p input_queue_t structure * @return The queue status. - * @retval FALSE if the queue is not full. - * @retval TRUE if the queue is full. + * @retval false if the queue is not full. + * @retval true if the queue is full. * * @iclass */ @@ -267,12 +267,12 @@ typedef io_queue_t output_queue_t; #define oqGetEmptyI(oqp) qSpaceI(oqp) /** - * @brief Evaluates to @p TRUE if the specified output queue is empty. + * @brief Evaluates to @p true if the specified output queue is empty. * - * @param[in] oqp pointer to an @p output_queue_t structure. + * @param[in] oqp pointer to an @p output_queue_t structure * @return The queue status. - * @retval FALSE if the queue is not empty. - * @retval TRUE if the queue is empty. + * @retval false if the queue is not empty. + * @retval true if the queue is empty. * * @iclass */ @@ -280,12 +280,12 @@ typedef io_queue_t output_queue_t; ((oqp)->q_counter != 0U))) /** - * @brief Evaluates to @p TRUE if the specified output queue is full. + * @brief Evaluates to @p true if the specified output queue is full. * - * @param[in] oqp pointer to an @p output_queue_t structure. + * @param[in] oqp pointer to an @p output_queue_t structure * @return The queue status. - * @retval FALSE if the queue is not full. - * @retval TRUE if the queue is full. + * @retval false if the queue is not full. + * @retval true if the queue is full. * * @iclass */ diff --git a/os/hal/src/hal_buffers.c b/os/hal/src/hal_buffers.c index 62d1dbbb4..f6a3e9319 100644 --- a/os/hal/src/hal_buffers.c +++ b/os/hal/src/hal_buffers.c @@ -45,42 +45,135 @@ /*===========================================================================*/ /** - * @brief Initializes an I/O buffer object. + * @brief Initializes an input double buffer object. * - * @param[out] iobp pointer to the @p input_double_buffer_t object - * @param[in] bp pointer to a memory area allocated as buffer - * @param[in] size size of the buffers + * @param[out] ibqp pointer to the @p io_buffers_queue_t object + * @param[in] bp pointer to a memory area allocated for buffers + * @param[in] size buffer size, including the size field which is the + * size of a @p size_t + * @param[in] n number of buffers + * @param[in] infy callback called when a buffer is returned to the queue + * @param[in] link application defined pointer * * @init */ -void iobInit(io_buffer_t *iobp, uint8_t *bp, size_t size) { +void ibqObjectInit(input_buffers_queue_t *ibqp, uint8_t *bp, + size_t size, size_t n, + dbnotify_t infy, void *link) { - iobp->buffer = bp; - iobp->limit = bp; - iobp->top = bp + size; + osalDbgCheck((ibqp != NULL) && (bp != NULL) && (size >= sizeof(size_t) + 2)); + + ibqp->bcounter = 0; + ibqp->brdptr = bp; + ibqp->bwrptr = bp; + ibqp->btop = bp + (size * n); /* Pre-calculated for speed.*/ + ibqp->bsize = size; + ibqp->bn = n; + ibqp->buffers = bp; + ibqp->ptr = NULL; + ibqp->notify = infy; + ibqp->link = link; } /** - * @brief Initializes an input double buffer object. + * @brief Gets a buffer for posting in the queue. + * @note The function always returns the same buffer if called repeatedly. * - * @param[out] idbp pointer to the @p input_double_buffer_t object - * @param[in] b1p pointer to a memory area allocated as buffer 1 - * @param[in] b2p pointer to a memory area allocated as buffer 2 - * @param[in] size size of the buffers + * @param[out] ibqp pointer to the @p input_buffers_queue_t object + * @return A pointer to the next buffer to be filled. + * @retval NULL if the queue is full. * - * @init + * @iclass */ -void idbObjectInit(input_double_buffer_t *idbp, - uint8_t *b1p, uint8_t *b2p, size_t size, - dbnotify_t infy, void *link) { +uint8_t *ibqGetNextBufferI(input_buffers_queue_t *ibqp) { + + osalDbgCheckClassI(); + + if (ibqIsFullI(ibqp)) { + return NULL; + } + + return ibqp->bwrptr + sizeof (size_t); +} + +/** + * @brief Posts a buffer in the queue. + * + * @param[out] ibqp pointer to the @p input_buffers_queue_t object + * @param[in] size used size of the buffer + * + * @iclass + */ +void ibqPostBufferI(io_buffers_queue_t *ibqp, size_t size) { + + osalDbgCheckClassI(); + osalDbgAssert(!ibqIsFullI(ibqp), "buffered queue full"); + + /* Writing size field in the buffer.*/ + *((size_t *)ibqp->bwrptr) = size; + + /* Posting the buffer in the queue.*/ + ibqp->bcounter++; + ibqp->bwrptr += ibqp->bsize; + if (ibqp->bwrptr >= ibqp->btop) { + ibqp->bwrptr = ibqp->buffers; + } + + /* Waking up one waiting thread, if any.*/ + osalThreadDequeueNextI(&ibqp->waiting, MSG_OK); +} + +/** + * @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 + * 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] 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 MSG_TIMEOUT if the specified time expired. + * @retval MSG_RESET if the queue has been reset. + * + * @api + */ +msg_t ibqGetTimeout(input_buffers_queue_t *ibqp, systime_t timeout) { + +} + +/** + * @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] ibqp pointer to the @p input_buffers_queue_t object + * @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] 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 number of bytes effectively transferred. + * + * @api + */ +size_t ibqReadTimeout(input_buffers_queue_t *ibqp, uint8_t *bp, + size_t n, systime_t timeout) { - iobInit(&idbp->buffers[0], b1p, size); - iobInit(&idbp->buffers[1], b2p, size); - idbp->counter = 0; - idbp->brdptr = &idbp->buffers[0]; - idbp->bwrptr = &idbp->buffers[0]; - idbp->notify = infy; - idbp->link = link; } /** @} */ diff --git a/os/rt/include/chqueues.h b/os/rt/include/chqueues.h index e48429d14..6b57a7e3c 100644 --- a/os/rt/include/chqueues.h +++ b/os/rt/include/chqueues.h @@ -195,7 +195,7 @@ typedef io_queue_t output_queue_t; /** * @brief Returns the queue's buffer size. * - * @param[in] qp pointer to a @p io_queue_t structure. + * @param[in] qp pointer to a @p io_queue_t structure * @return The buffer size. * * @xclass @@ -210,7 +210,7 @@ typedef io_queue_t output_queue_t; * @details Returns the used space if used on an input queue or the empty * space if used on an output queue. * - * @param[in] qp pointer to a @p io_queue_t structure. + * @param[in] qp pointer to a @p io_queue_t structure * @return The buffer space. * * @iclass @@ -220,7 +220,7 @@ typedef io_queue_t output_queue_t; /** * @brief Returns the queue application-defined link. * - * @param[in] qp pointer to a @p io_queue_t structure. + * @param[in] qp pointer to a @p io_queue_t structure * @return The application-defined link. * * @xclass @@ -293,7 +293,7 @@ static inline size_t chIQGetEmptyI(input_queue_t *iqp) { /** * @brief Evaluates to @p true if the specified input queue is empty. * - * @param[in] iqp pointer to an @p input_queue_t structure. + * @param[in] iqp pointer to an @p input_queue_t structure * @return The queue status. * @retval false if the queue is not empty. * @retval true if the queue is empty. @@ -310,7 +310,7 @@ static inline bool chIQIsEmptyI(input_queue_t *iqp) { /** * @brief Evaluates to @p true if the specified input queue is full. * - * @param[in] iqp pointer to an @p input_queue_t structure. + * @param[in] iqp pointer to an @p input_queue_t structure * @return The queue status. * @retval false if the queue is not full. * @retval true if the queue is full. @@ -376,7 +376,7 @@ static inline size_t chOQGetEmptyI(output_queue_t *oqp) { /** * @brief Evaluates to @p true if the specified output queue is empty. * - * @param[in] oqp pointer to an @p output_queue_t structure. + * @param[in] oqp pointer to an @p output_queue_t structure * @return The queue status. * @retval false if the queue is not empty. * @retval true if the queue is empty. @@ -393,7 +393,7 @@ static inline bool chOQIsEmptyI(output_queue_t *oqp) { /** * @brief Evaluates to @p true if the specified output queue is full. * - * @param[in] oqp pointer to an @p output_queue_t structure. + * @param[in] oqp pointer to an @p output_queue_t structure * @return The queue status. * @retval false if the queue is not full. * @retval true if the queue is full.