diff options
Diffstat (limited to 'os/kernel')
-rw-r--r-- | os/kernel/include/ch.h | 1 | ||||
-rw-r--r-- | os/kernel/include/channels.h | 127 | ||||
-rw-r--r-- | os/kernel/include/queues.h | 14 | ||||
-rw-r--r-- | os/kernel/include/streams.h | 106 | ||||
-rw-r--r-- | os/kernel/kernel.dox | 31 | ||||
-rw-r--r-- | os/kernel/src/chqueues.c | 145 |
6 files changed, 292 insertions, 132 deletions
diff --git a/os/kernel/include/ch.h b/os/kernel/include/ch.h index 5d15b13ae..ecac6f3f7 100644 --- a/os/kernel/include/ch.h +++ b/os/kernel/include/ch.h @@ -81,6 +81,7 @@ #include "threads.h"
#include "inline.h"
#include "queues.h"
+#include "streams.h"
#include "channels.h"
#include "debug.h"
diff --git a/os/kernel/include/channels.h b/os/kernel/include/channels.h index e9cc956a6..66f1d1168 100644 --- a/os/kernel/include/channels.h +++ b/os/kernel/include/channels.h @@ -19,7 +19,7 @@ /**
* @file channels.h
- * @brief I/O channels
+ * @brief I/O channels.
* @addtogroup io_channels
* @{
*/
@@ -45,12 +45,22 @@ struct _base_channel_methods { * @brief Channel put method with timeout specification.
* @see chIOPut()
*/
- msg_t (*put)(void *instance, uint8_t b, systime_t timeout);
+ msg_t (*put)(void *instance, uint8_t b, systime_t time);
/**
* @brief Channel get method with timeout specification.
* @see chIOGet()
*/
- msg_t (*get)(void *instance, systime_t timeout);
+ msg_t (*get)(void *instance, systime_t time);
+ /**
+ * @brief Channel write method with timeout specification.
+ * @see chIOWrite()
+ */
+ size_t (*write)(void *instance, const uint8_t *bp, size_t n, systime_t time);
+ /**
+ * @brief Channel read method with timeout specification.
+ * @see chIORead()
+ */
+ size_t (*read)(void *instance, uint8_t *bp, size_t n, systime_t time);
};
/**
@@ -66,14 +76,21 @@ struct _base_channel_data { */
struct BaseChannelVMT {
/**
+ * @p BaseSequentialStream class inherited methods.
+ */
+ struct _base_sequental_stream_methods bss;
+ /**
* @p BaseChannel class specific methods.
*/
struct _base_channel_methods bc;
};
/**
+ * @extends BaseSequentialStream
+ *
* @brief Base channel class.
- * @details This class represents a generic, byte-wide, I/O channel. + * @details This class represents a generic, byte-wide, I/O channel. This class
+ * introduces generic I/O primitives with timeout specification. */
typedef struct {
/**
@@ -81,6 +98,10 @@ typedef struct { */
const struct BaseChannelVMT *vmt;
/**
+ * @p BaseSequentialStream class inherited data.
+ */
+ struct _base_sequental_stream_data bss;
+ /**
* @p BaseChannel class specific data.
*/
struct _base_channel_data bc;
@@ -88,7 +109,8 @@ typedef struct { /**
* @brief Channel output check.
- * @details This function verifies if a subsequent @p chIOPut() would block.
+ * @details This function verifies if a subsequent put/write operation would
+ * block.
*
* @param[in] ip pointer to a @p BaseChannel or derived class
* @return The output queue status:
@@ -100,7 +122,8 @@ typedef struct { /**
* @brief Channel input check.
- * @details This function verifies if a subsequent @p chIOGett() would block.
+ * @details This function verifies if a subsequent get/read operation would
+ * block.
*
* @param[in] ip pointer to a @p BaseChannel or derived class
* @return The input queue status:
@@ -130,7 +153,7 @@ typedef struct { *
* @param[in] ip pointer to a @p BaseChannel or derived class
* @param[in] b the byte value to be written to the channel
- * @param[in] timeout the number of ticks before the operation timeouts,
+ * @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.
@@ -140,7 +163,7 @@ typedef struct { * @retval Q_TIMEOUT if the specified time expired.
* @retval Q_RESET if the channel associated queue (if any) was reset.
*/
-#define chIOPutTimeout(ip, b, timeout) ((ip)->vmt->bc.put(ip, b, timeout))
+#define chIOPutTimeout(ip, b, time) ((ip)->vmt->bc.put(ip, b, time))
/**
* @brief Channel blocking byte read.
@@ -159,7 +182,7 @@ typedef struct { * is not available then the calling thread is suspended.
*
* @param[in] ip pointer to a @p BaseChannel or derived class
- * @param[in] timeout the number of ticks before the operation timeouts,
+ * @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.
@@ -168,23 +191,49 @@ typedef struct { * @retval Q_TIMEOUT if the specified time expired.
* @retval Q_RESET if the channel associated queue (if any) was reset.
*/
-#define chIOGetTimeout(ip, timeout) ((ip)->vmt->bc.get(ip, timeout))
+#define chIOGetTimeout(ip, time) ((ip)->vmt->bc.get(ip, time))
+
+/**
+ * @brief Channel blocking write with timeout.
+ * @details The function writes data from a buffer to a channel. If the channel
+ * is not ready to accept data then the calling thread is suspended.
+ *
+ * @param[in] ip pointer to a @p BaseChannel or derived class
+ * @param[out] bp pointer to the data buffer
+ * @param[in] n the maximum amount of data to be transferred
+ * @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 transferred.
+ */
+#define chIOWriteTimeout(ip, bp, n, time) \
+ ((ip)->vmt->bac.write(ip, bp, n, time))
+
+/**
+ * @brief Channel blocking read with timeout.
+ * @details The function reads data from a channel into a buffer. If the data
+ * is not available then the calling thread is suspended.
+ *
+ * @param[in] ip pointer to a @p BaseChannel or derived class
+ * @param[in] bp pointer to the data buffer
+ * @param[in] n the maximum amount of data to be transferred
+ * @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 transferred.
+ */
+#define chIOReadTimeout(ip, bp, n, time) \
+ ((ip)->vmt->bac.read(ip, bp, n, time))
#if CH_USE_EVENTS
/**
* @brief @p BaseAsynchronousChannel specific methods.
*/
struct _base_asynchronous_channel_methods {
- /**
- * Channel asynchronous write method.
- * @see chIOWrite()
- */
- size_t (*write)(void *instance, uint8_t *buffer, size_t n);
- /**
- * Channel asynchronous read method.
- * @see chIORead()
- */
- size_t (*read)(void *instance, uint8_t *buffer, size_t n);
};
/**
@@ -208,6 +257,10 @@ struct _base_asynchronous_channel_data { */
struct BaseAsynchronousChannelVMT {
/**
+ * @p BaseSequentialStream class inherited methods.
+ */
+ struct _base_sequental_stream_methods bss;
+ /**
* @p BaseChannel class inherited methods.
*/
struct _base_channel_methods bc;
@@ -221,8 +274,8 @@ struct BaseAsynchronousChannelVMT { * @extends BaseChannel
*
* @brief Base asynchronous channel class.
- * @details This class extends @p BaseChannel by adding methods for
- * asynchronous I/O in an event-driven environment. + * @details This class extends @p BaseChannel by adding event sources fields
+ * for asynchronous I/O for use in an event-driven environment. */
typedef struct {
/**
@@ -230,6 +283,10 @@ typedef struct { */
const struct BaseAsynchronousChannelVMT *vmt;
/**
+ * @p BaseSequentialStream class inherited data.
+ */
+ struct _base_sequental_stream_data bss;
+ /**
* @p BaseChannel class inherited data.
*/
struct _base_channel_data bc;
@@ -240,32 +297,6 @@ typedef struct { } BaseAsynchronousChannel;
/**
- * @brief Channel non-blocking write.
- * @details The function writes data from a buffer to a channel. The
- * transfer is non-blocking and can return zero if the channel is
- * not read to accept data.
- *
- * @param[in] ip pointer to a @p BaseAsynchronousChannel or derived class
- * @param[out] bp pointer to the buffer where the data is stored
- * @param[in] n the maximum amount of data to be transferred
- * @return The number of bytes transferred.
- */
-#define chIOWrite(ip, bp, n) ((ip)->vmt->bac.write(ip, bp, n))
-
-/**
- * @brief Channel non-blocking read.
- * @details The function reads data from a channel into a buffer. The
- * transfer is non-blocking and can return zero if the channel has
- * no data immediately available.
- *
- * @param[in] ip pointer to a @p BaseAsynchronousChannel or derived class
- * @param[out] bp 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.
- */
-#define chIORead(ip, bp, n) ((ip)->vmt->bac.read(ip, bp, n))
-
-/**
* @brief Returns the write event source.
* @details The write event source is broadcasted when the channel is ready
* for write operations. This usually happens when the internal
diff --git a/os/kernel/include/queues.h b/os/kernel/include/queues.h index 25ba82d65..93a2ab7b2 100644 --- a/os/kernel/include/queues.h +++ b/os/kernel/include/queues.h @@ -205,17 +205,19 @@ typedef GenericQueue OutputQueue; #ifdef __cplusplus extern "C" { #endif - void chIQInit(InputQueue *qp, uint8_t *buffer, size_t size, qnotify_t inotify); + void chIQInit(InputQueue *qp, uint8_t *bp, size_t size, qnotify_t infy); 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); + msg_t chIQGetTimeout(InputQueue *qp, systime_t time); + size_t chIQReadTimeout(InputQueue *qp, uint8_t *bp, + size_t n, systime_t time); - void chOQInit(OutputQueue *queue, uint8_t *buffer, size_t size, qnotify_t onotify); + void chOQInit(OutputQueue *queue, uint8_t *bp, size_t size, qnotify_t onfy); void chOQResetI(OutputQueue *queue); - msg_t chOQPutTimeout(OutputQueue *queue, uint8_t b, systime_t timeout); + msg_t chOQPutTimeout(OutputQueue *queue, uint8_t b, systime_t time); msg_t chOQGetI(OutputQueue *queue); - size_t chOQWrite(OutputQueue *queue, uint8_t *buffer, size_t n); + size_t chOQWriteTimeout(OutputQueue *queue, const uint8_t *bp, + size_t n, systime_t time); #ifdef __cplusplus } #endif diff --git a/os/kernel/include/streams.h b/os/kernel/include/streams.h new file mode 100644 index 000000000..f01d0999b --- /dev/null +++ b/os/kernel/include/streams.h @@ -0,0 +1,106 @@ +/*
+ ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file streams.h
+ * @brief Data streams.
+ * @addtogroup data_streams
+ * @{
+ */
+
+#ifndef _STREAMS_H_
+#define _STREAMS_H_
+
+/**
+ * @brief BaseSequentialStream specific methods.
+ */
+struct _base_sequental_stream_methods {
+ /**
+ * @brief Stream write buffer method.
+ */
+ size_t (*write)(void *instance, const uint8_t *bp, size_t n);
+ /**
+ * @brief Stream read buffer method.
+ */
+ size_t (*read)(void *instance, uint8_t *bp, size_t n);
+};
+
+/**
+ * @brief @p BaseSequentialStream specific data.
+ * @note It is empty because @p BaseSequentialStream is only an interface
+ * without implementation.
+ */
+struct _base_sequental_stream_data {
+};
+
+/**
+ * @brief @p BaseSequentialStream virtual methods table.
+ */
+struct BaseSequentialStreamVMT {
+ /**
+ * @p BaseSequentialStream class specific methods.
+ */
+ struct _base_sequental_stream_methods bss;
+};
+
+/**
+ * @brief Base stream class.
+ * @details This class represents a generic blocking unbuffered sequential
+ * data stream.
+ */
+typedef struct {
+ /**
+ * Virtual Methods Table.
+ */
+ const struct BaseSequentialStreamVMT *vmt;
+ /**
+ * @p BaseSequentialStream class specific data.
+ */
+ struct _base_sequental_stream_data bss;
+} BaseSequentialStream;
+
+/**
+ * @brief Sequential Stream write.
+ * @details The function writes data from a buffer to a stream.
+ *
+ * @param[in] ip pointer to a @p BaseSequentialStream or derived class
+ * @param[in] bp pointer to the data buffer
+ * @param[in] n the maximum amount of data to be transferred
+ * @return The number of bytes transferred. The return value can be less
+ * than the specified number of bytes if the stream reaches a
+ * physical end of file and cannot be extended.
+ */
+#define chSequentialStreamWrite(ip, bp, n) ((ip)->vmt->bss.write(ip, bp, n))
+
+/**
+ * @brief Sequential Stream read.
+ * @details The function reads data from a stream into a buffer.
+ *
+ * @param[in] ip pointer to a @p BaseSequentialStream or derived class
+ * @param[out] bp pointer to the data buffer
+ * @param[in] n the maximum amount of data to be transferred
+ * @return The number of bytes transferred. The return value can be less
+ * than the specified number of bytes if the stream reaches the end
+ * of the available data.
+ */
+#define chSequentialStreamRead(ip, bp, n) ((ip)->vmt->bss.read(ip, bp, n))
+
+#endif /* _STREAMS_H_ */
+
+/** @} */
diff --git a/os/kernel/kernel.dox b/os/kernel/kernel.dox index 0f544d04e..072be41ec 100644 --- a/os/kernel/kernel.dox +++ b/os/kernel/kernel.dox @@ -283,17 +283,30 @@ */
/**
+ * @defgroup data_streams Streams
+ * @brief Streams.
+ * @details This module define an abstract interface for generic data streams.
+ * Note that no code is present, streams are just abstract classes-like
+ * structures, you should look at the systems as to a set of abstract C++
+ * classes (even if written in C). This system has the advantage to make the
+ * access to streams independent from the implementation logic.<br>
+ * The stream interface can be used as base class for high level object types
+ * such as files, sockets, serial ports, pipes etc.
+ *
+ * @ingroup io_support
+ */
+
+/**
* @defgroup io_channels I/O Abstract Channels
* @brief Abstract I/O Channels.
- * @details This module defines an abstract interface for I/O channels. Note
- * that no code is present, I/O channels are just abstract classes-like
- * structures, you should look at the systems as to a set of abstract C++
- * classes (even if written in C). Specific device drivers can use/extend
- * the interfaces and implement them.<br>
+ * @details This module defines an abstract interface for I/O channels by
+ * extending the @p BaseSequentialStream interface. Note that no code is
+ * present, I/O channels are just abstract classes-like structures,
+ * you should look at the systems as to a set of abstract C++ classes
+ * (even if written in C). Specific device drivers can use/extend the
+ * interface and implement them.<br>
* This system has the advantage to make the access to channels
- * independent from the implementation logic. As example, an I/O channel
- * interface can hide the access to a serial driver, to a networking socket
- * and so on.
+ * independent from the implementation logic.
*
* @ingroup io_support
*/
@@ -317,6 +330,8 @@ * .
* In order to use the I/O queues the @p CH_USE_QUEUES option must
* be specified in @p chconf.h.<br>
+ * I/O queues are usually used as an implementation layer for the I/O channels
+ * interface.
*
* @ingroup io_support
*/
diff --git a/os/kernel/src/chqueues.c b/os/kernel/src/chqueues.c index a346ee07f..f4111a814 100644 --- a/os/kernel/src/chqueues.c +++ b/os/kernel/src/chqueues.c @@ -34,33 +34,30 @@ * the bytes contained in the queue.
*
* @param[out] iqp pointer to an @p InputQueue structure
- * @param[in] buffer pointer to a memory area allocated as queue buffer
+ * @param[in] bp 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.
+ * @param[in] infy pointer to a callback function that is invoked when
+ * 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(InputQueue *iqp, uint8_t *buffer,
- size_t size, qnotify_t inotify) {
+void chIQInit(InputQueue *iqp, uint8_t *bp, size_t size, qnotify_t infy) {
- iqp->q_buffer = iqp->q_rdptr = iqp->q_wrptr = buffer;
- iqp->q_top = buffer + size;
+ iqp->q_buffer = iqp->q_rdptr = iqp->q_wrptr = bp;
+ iqp->q_top = bp + size;
+ iqp->q_notify = infy;
chSemInit(&iqp->q_sem, 0);
- iqp->q_notify = inotify;
}
/**
* @brief Resets an input queue.
* @details All the data in the input queue is erased and lost, any waiting
* thread is resumed with status @p Q_RESET.
- *
- * @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.
+ *
+ * @param[in] iqp pointer to an @p InputQueue structure
*/
void chIQResetI(InputQueue *iqp) {
@@ -97,7 +94,7 @@ msg_t chIQPutI(InputQueue *iqp, uint8_t b) { * in the queue or a timeout occurs.
*
* @param[in] iqp pointer to an @p InputQueue structure
- * @param[in] timeout the number of ticks before the operation timeouts,
+ * @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.
@@ -106,12 +103,12 @@ msg_t chIQPutI(InputQueue *iqp, uint8_t b) { * @retval Q_TIMEOUT if the specified time expired.
* @retval Q_RESET if the queue was reset.
*/
-msg_t chIQGetTimeout(InputQueue *iqp, systime_t timeout) {
+msg_t chIQGetTimeout(InputQueue *iqp, systime_t time) {
uint8_t b;
msg_t msg;
chSysLock();
- if ((msg = chSemWaitTimeoutS(&iqp->q_sem, timeout)) < RDY_OK) {
+ if ((msg = chSemWaitTimeoutS(&iqp->q_sem, time)) < RDY_OK) {
chSysUnlock();
return msg;
}
@@ -127,40 +124,45 @@ msg_t chIQGetTimeout(InputQueue *iqp, systime_t timeout) { }
/**
- * @brief Non-blocking read.
+ * @brief Input queue read with timeout.
* @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.
+ * 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 one time <b>for each</b> byte removed
+ * from the queue.
*
* @param[in] iqp pointer to an @p InputQueue structure
- * @param[out] buffer pointer to the buffer where the input data is copied
+ * @param[out] bp pointer to the data buffer
* @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.
+ * @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.
*/
-size_t chIQRead(InputQueue *iqp, uint8_t *buffer, size_t n) {
+size_t chIQReadTimeout(InputQueue *iqp, uint8_t *bp,
+ size_t n, systime_t time) {
+ qnotify_t nfy = iqp->q_notify;
size_t r = 0;
- while (n--) {
+ do {
chSysLock();
- if (chIQIsEmpty(iqp)) {
+ if (chSemWaitTimeoutS(&iqp->q_sem, time) != RDY_OK) {
chSysUnlock();
- break;
+ return r;
}
- chSemFastWaitI(&iqp->q_sem);
- *buffer++ = *iqp->q_rdptr++;
+ *bp++ = *iqp->q_rdptr++;
if (iqp->q_rdptr >= iqp->q_top)
iqp->q_rdptr = iqp->q_buffer;
- chSysUnlock();
+ if (nfy)
+ nfy();
+ chSysUnlock(); /* Gives a preemption chance in a controlled point.*/
r++;
- }
- if (r && iqp->q_notify) {
- chSysLock();
- iqp->q_notify();
- chSysUnlock();
- }
+ } while (--n > 0);
return r;
}
@@ -170,22 +172,20 @@ size_t chIQRead(InputQueue *iqp, uint8_t *buffer, size_t n) { * the free bytes in the queue.
*
* @param[out] oqp pointer to an @p OutputQueue structure
- * @param[in] buffer pointer to a memory area allocated as queue buffer
+ * @param[in] bp 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 to the queue. The value can be
- * @p NULL.
+ * @param[in] onfy pointer to a callback function that is invoked when
+ * 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(OutputQueue *oqp, uint8_t *buffer,
- size_t size, qnotify_t onotify) {
+void chOQInit(OutputQueue *oqp, uint8_t *bp, size_t size, qnotify_t onfy) {
- oqp->q_buffer = oqp->q_rdptr = oqp->q_wrptr = buffer;
- oqp->q_top = buffer + size;
+ oqp->q_buffer = oqp->q_rdptr = oqp->q_wrptr = bp;
+ oqp->q_top = bp + size;
+ oqp->q_notify = onfy;
chSemInit(&oqp->q_sem, size);
- oqp->q_notify = onotify;
}
/**
@@ -212,7 +212,7 @@ void chOQResetI(OutputQueue *oqp) { *
* @param[in] oqp pointer to an @p OutputQueue structure
* @param[in] b the byte value to be written in the queue
- * @param[in] timeout the number of ticks before the operation timeouts,
+ * @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.
@@ -222,11 +222,11 @@ void chOQResetI(OutputQueue *oqp) { * @retval Q_TIMEOUT if the specified time expired.
* @retval Q_RESET if the queue was reset.
*/
-msg_t chOQPutTimeout(OutputQueue *oqp, uint8_t b, systime_t timeout) {
+msg_t chOQPutTimeout(OutputQueue *oqp, uint8_t b, systime_t time) {
msg_t msg;
chSysLock();
- if ((msg = chSemWaitTimeoutS(&oqp->q_sem, timeout)) < RDY_OK) {
+ if ((msg = chSemWaitTimeoutS(&oqp->q_sem, time)) < RDY_OK) {
chSysUnlock();
return msg;
}
@@ -263,40 +263,45 @@ msg_t chOQGetI(OutputQueue *oqp) { }
/**
- * @brief Non-blocking write.
+ * @brief Output queue write with timeout.
* @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.
+ * 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 one time <b>for each</b> byte inserted
+ * into the queue.
*
* @param[in] oqp pointer to an @p OutputQueue structure
- * @param[out] buffer pointer to the buffer where the output data is stored
+ * @param[out] bp pointer to the data buffer
* @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.
+ * @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.
*/
-size_t chOQWrite(OutputQueue *oqp, uint8_t *buffer, size_t n) {
-
+size_t chOQWriteTimeout(OutputQueue *oqp, const uint8_t *bp,
+ size_t n, systime_t time) {
+ qnotify_t nfy = oqp->q_notify;
size_t w = 0;
- while (n--) {
+
+ do {
chSysLock();
- if (chOQIsFull(oqp)) {
+ if (chSemWaitTimeoutS(&oqp->q_sem, time) != RDY_OK) {
chSysUnlock();
- break;
+ return w;
}
- chSemFastWaitI(&oqp->q_sem);
- *oqp->q_wrptr++ = *buffer++;
+ *oqp->q_wrptr++ = *bp++;
if (oqp->q_wrptr >= oqp->q_top)
oqp->q_wrptr = oqp->q_buffer;
- chSysUnlock();
+ if (nfy)
+ nfy();
+ chSysUnlock(); /* Gives a preemption chance in a controlled point.*/
w++;
- }
- if (w && oqp->q_notify) {
- chSysLock();
- oqp->q_notify();
- chSysUnlock();
- }
+ } while (--n > 0);
return w;
}
#endif /* CH_USE_QUEUES */
|