git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@8619 35acf78f-673a-0410-8e92-d51de3d6d3f4

This commit is contained in:
Giovanni Di Sirio 2015-12-20 09:45:43 +00:00
parent f6616d5708
commit ddcc89f8d1
4 changed files with 229 additions and 95 deletions

View File

@ -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 <tt>sizeof(size_t) + 2</tt>
* 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
}

View File

@ -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
*/

View File

@ -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;
}
/** @} */

View File

@ -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.