aboutsummaryrefslogtreecommitdiffstats
path: root/os
diff options
context:
space:
mode:
authorgdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2010-01-05 17:14:09 +0000
committergdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2010-01-05 17:14:09 +0000
commit855fe2391d07c5dab27129ad626541482fe8d782 (patch)
tree93d4213cd7de59ab0d1b930e653d60fbf8914dc4 /os
parentde95f94fbeb425a7e36e664181824db6ed021ccc (diff)
downloadChibiOS-855fe2391d07c5dab27129ad626541482fe8d782.tar.gz
ChibiOS-855fe2391d07c5dab27129ad626541482fe8d782.tar.bz2
ChibiOS-855fe2391d07c5dab27129ad626541482fe8d782.zip
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@1501 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os')
-rw-r--r--os/hal/hal.dox12
-rw-r--r--os/hal/include/serial.h83
-rw-r--r--os/hal/src/serial.c31
-rw-r--r--os/kernel/include/ch.h1
-rw-r--r--os/kernel/include/channels.h127
-rw-r--r--os/kernel/include/queues.h14
-rw-r--r--os/kernel/include/streams.h106
-rw-r--r--os/kernel/kernel.dox31
-rw-r--r--os/kernel/src/chqueues.c145
-rw-r--r--os/various/syscalls.c12
10 files changed, 394 insertions, 168 deletions
diff --git a/os/hal/hal.dox b/os/hal/hal.dox
index 81b5a148d..657185f8e 100644
--- a/os/hal/hal.dox
+++ b/os/hal/hal.dox
@@ -26,17 +26,17 @@
* - High Level Device Driver (<b>HLD</b>). This layer contains the definitions
* of the driver's APIs and the platform independent part of the driver.<br>
* An HLD is composed by two files:
- * - @<driver@>.c, the high level implementation file. This file must be
+ * - @<driver@>.c, the HLD implementation file. This file must be
* included in the Makefile in order to use the driver.
- * - @<driver@>.h, the high level header file. This file must be included
- * by the application code in order to access the driver's APIs.
+ * - @<driver@>.h, the HLD header file. This file is implicitly
+ * included by the HAL header file @p hal.h.
* .
* - Low Level Device Driver (<b>LLD</b>). This layer contains the platform
* dependent part of the driver.<br>
* A LLD is composed by two files:
- * - @<driver@>_lld.c, the low level implementation file. This file must be
+ * - @<driver@>_lld.c, the LLD implementation file. This file must be
* included in the Makefile in order to use the driver.
- * - @<driver@>_lld.h, the high level header file. This file is implicitly
+ * - @<driver@>_lld.h, the LLD header file. This file is implicitly
* included by the HLD header file.
* .
* The LLD may be not present in those drivers that do not access the
@@ -174,7 +174,7 @@
* @dot
digraph example {
rankdir="LR";
- node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true", width="0.75", height="0.75"];
+ node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true", width="0.8", height="0.8"];
edge [fontname=Helvetica, fontsize=8];
uninit [label="SPI_UNINIT", style="bold"];
stop [label="SPI_STOP\nLow Power"];
diff --git a/os/hal/include/serial.h b/os/hal/include/serial.h
index c24ac3994..3f4a1a8ca 100644
--- a/os/hal/include/serial.h
+++ b/os/hal/include/serial.h
@@ -108,6 +108,10 @@ struct _serial_driver_methods {
*/
struct SerialDriverVMT {
/**
+ * @p BaseSequentialStream class inherited methods.
+ */
+ struct _base_sequental_stream_methods bss;
+ /**
* @p BaseChannel class inherited methods.
*/
struct _base_channel_methods bc;
@@ -134,6 +138,10 @@ struct _SerialDriver {
*/
const struct SerialDriverVMT *vmt;
/**
+ * @p BaseSequentialStream class inherited data.
+ */
+ struct _base_sequental_stream_data bss;
+ /**
* @p BaseChannel class inherited data.
*/
struct _base_channel_data bc;
@@ -170,7 +178,7 @@ struct _SerialDriver {
#define sdGetWouldBlock(sdp) chIQIsEmpty(&(sdp)->sd.iqueue)
/**
- * @brief Direct blocking write to a @p SerialDriver.
+ * @brief Direct write to a @p SerialDriver.
* @details This function bypasses the indirect access to the channel and
* writes directly on the output queue. This is faster but cannot
* be used to write to different channels implementations.
@@ -179,8 +187,7 @@ struct _SerialDriver {
#define sdPut(sdp, b) chOQPut(&(sdp)->sd.oqueue, b)
/**
- * @brief Direct blocking write on a @p SerialDriver with timeout
- * specification.
+ * @brief Direct write to a @p SerialDriver with timeout specification.
* @details This function bypasses the indirect access to the channel and
* writes directly on the output queue. This is faster but cannot
* be used to write to different channels implementations.
@@ -189,7 +196,7 @@ struct _SerialDriver {
#define sdPutTimeout(sdp, b, t) chOQPutTimeout(&(sdp)->sd.iqueue, b, t)
/**
- * @brief Direct blocking read from a @p SerialDriver.
+ * @brief Direct read from a @p SerialDriver.
* @details This function bypasses the indirect access to the channel and
* reads directly from the input queue. This is faster but cannot
* be used to read from different channels implementations.
@@ -198,8 +205,7 @@ struct _SerialDriver {
#define sdGet(sdp) chIQGet(&(sdp)->sd.iqueue)
/**
- * @brief Direct blocking read from a @p SerialDriver with timeout
- * specification.
+ * @brief Direct read from a @p SerialDriver with timeout specification.
* @details This function bypasses the indirect access to the channel and
* reads directly from the input queue. This is faster but cannot
* be used to read from different channels implementations.
@@ -208,22 +214,77 @@ struct _SerialDriver {
#define sdGetTimeout(sdp, t) chIQGetTimeout(&(sdp)->sd.iqueue, t)
/**
+ * @brief Direct blocking write to a @p SerialDriver.
+ * @details This function bypasses the indirect access to the channel and
+ * writes directly to the output queue. This is faster but cannot
+ * be used to write from different channels implementations.
+ * @see chIOWriteTimeout()
+ */
+#define sdWrite(sdp, b, n) \
+ chOQWriteTimeout(&(sdp)->sd.oqueue, b, n, TIME_INFINITE)
+
+/**
+ * @brief Direct blocking write to a @p SerialDriver with timeout
+ * specification.
+ * @details This function bypasses the indirect access to the channel and
+ * writes directly to the output queue. This is faster but cannot
+ * be used to write from different channels implementations.
+ * @see chIOWriteTimeout()
+ */
+#define sdWriteTimeout(sdp, b, n, t) \
+ chOQWriteTimeout(&(sdp)->sd.oqueue, b, n, t)
+
+/**
* @brief Direct non-blocking write to a @p SerialDriver.
* @details This function bypasses the indirect access to the channel and
* writes directly to the output queue. This is faster but cannot
* be used to write from different channels implementations.
- * @see chIOWrite()
+ * @see chIOWriteTimeout()
*/
-#define sdWrite(sdp, b, n) chOQWrite(&(sdp)->sd.oqueue, b, n)
+#define sdAsynchronousWrite(sdp, b, n) \
+ chOQWriteTimeout(&(sdp)->sd.oqueue, b, n, TIME_IMMEDIATE)
/**
- * @brief Direct non-blocking read on a @p SerialDriver.
+ * @brief Direct blocking read from a @p SerialDriver.
+ * @details This function bypasses the indirect access to the channel and
+ * reads directly from the input queue. This is faster but cannot
+ * be used to read from different channels implementations.
+ * @see chIOReadTimeout()
+ */
+#define sdRead(sdp, b, n) \
+ chIQReadTimeout(&(sdp)->sd.iqueue, b, n, TIME_INFINITE)
+
+/**
+ * @brief Direct blocking read from a @p SerialDriver with timeout
+ * specification.
* @details This function bypasses the indirect access to the channel and
* reads directly from the input queue. This is faster but cannot
* be used to read from different channels implementations.
- * @see chIORead()
+ * @see chIOReadTimeout()
+ */
+#define sdReadTimeout(sdp, b, n, t) \
+ chIQReadTimeout(&(sdp)->sd.iqueue, b, n, t)
+
+/**
+ * @brief Direct non-blocking read from a @p SerialDriver.
+ * @details This function bypasses the indirect access to the channel and
+ * reads directly from the input queue. This is faster but cannot
+ * be used to read from different channels implementations.
+ * @see chIOReadTimeout()
+ */
+#define sdAsynchronousRead(sdp, b, n) \
+ chIQReadTimeout(&(sdp)->sd.iqueue, b, n, TIME_IMMEDIATE)
+
+/**
+ * @brief Returns the status change event source.
+ * @details The status change event source is broadcasted when the channel
+ * status is updated, the status flags can then be fetched and
+ * cheared by using @p sdGetAndClearFlags().
+ *
+ * @param[in] ip pointer to a @p SerialDriver object
+ * @return A pointer to an @p EventSource object.
*/
-#define sdRead(sdp, b, n) chIQRead(&(sdp)->sd.iqueue, b, n)
+#define sdGetStatusChangeEventSource(ip) (&((ip)->vmt->sd.sevent))
/*===========================================================================*/
/* External declarations. */
diff --git a/os/hal/src/serial.c b/os/hal/src/serial.c
index 4c2cb71c9..54db8e95d 100644
--- a/os/hal/src/serial.c
+++ b/os/hal/src/serial.c
@@ -45,6 +45,19 @@
* Interface implementation, the following functions just invoke the equivalent
* queue-level function or macro.
*/
+
+static size_t writes(void *ip, const uint8_t *bp, size_t n) {
+
+ return chOQWriteTimeout(&((SerialDriver *)ip)->sd.oqueue, bp,
+ n, TIME_INFINITE);
+}
+
+static size_t reads(void *ip, uint8_t *bp, size_t n) {
+
+ return chIQReadTimeout(&((SerialDriver *)ip)->sd.iqueue, bp,
+ n, TIME_INFINITE);
+}
+
static bool_t putwouldblock(void *ip) {
return chOQIsFull(&((SerialDriver *)ip)->sd.oqueue);
@@ -55,29 +68,29 @@ static bool_t getwouldblock(void *ip) {
return chIQIsEmpty(&((SerialDriver *)ip)->sd.iqueue);
}
-static msg_t put(void *ip, uint8_t b, systime_t timeout) {
+static msg_t putt(void *ip, uint8_t b, systime_t timeout) {
return chOQPutTimeout(&((SerialDriver *)ip)->sd.oqueue, b, timeout);
}
-static msg_t get(void *ip, systime_t timeout) {
+static msg_t gett(void *ip, systime_t timeout) {
return chIQGetTimeout(&((SerialDriver *)ip)->sd.iqueue, timeout);
}
-static size_t write(void *ip, uint8_t *buffer, size_t n) {
+static size_t writet(void *ip, const uint8_t *bp, size_t n, systime_t time) {
- return chOQWrite(&((SerialDriver *)ip)->sd.oqueue, buffer, n);
+ return chOQWriteTimeout(&((SerialDriver *)ip)->sd.oqueue, bp, n, time);
}
-static size_t read(void *ip, uint8_t *buffer, size_t n) {
+static size_t readt(void *ip, uint8_t *bp, size_t n, systime_t time) {
- return chIQRead(&((SerialDriver *)ip)->sd.iqueue, buffer, n);
+ return chIQReadTimeout(&((SerialDriver *)ip)->sd.iqueue, bp, n, time);
}
static const struct SerialDriverVMT vmt = {
- {putwouldblock, getwouldblock, put, get},
- {write, read},
+ {writes, reads},
+ {putwouldblock, getwouldblock, putt, gett, writet, readt},
{}
};
@@ -112,10 +125,10 @@ void sdObjectInit(SerialDriver *sdp, qnotify_t inotify, qnotify_t onotify) {
chEvtInit(&sdp->bac.ievent);
chEvtInit(&sdp->bac.oevent);
chEvtInit(&sdp->sd.sevent);
+ sdp->sd.state = SD_STOP;
sdp->sd.flags = SD_NO_ERROR;
chIQInit(&sdp->sd.iqueue, sdp->sd.ib, SERIAL_BUFFERS_SIZE, inotify);
chOQInit(&sdp->sd.oqueue, sdp->sd.ob, SERIAL_BUFFERS_SIZE, onotify);
- sdp->sd.state = SD_STOP;
}
/**
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 */
diff --git a/os/various/syscalls.c b/os/various/syscalls.c
index abce2eea8..5c886f8f5 100644
--- a/os/various/syscalls.c
+++ b/os/various/syscalls.c
@@ -78,9 +78,7 @@ int _read_r(struct _reent *r, int file, char * ptr, int len)
__errno_r(r) = EINVAL;
return -1;
}
- *ptr++ = chIOGet(&STDOUT_SD);
- if (--len > 0)
- len = chIORead(&STDOUT_SD, (uint8_t *)ptr, (size_t)len);
+ len = sdRead(&STDOUT_SD, (uint8_t *)ptr, (size_t)len);
return len;
#else
(void)file;
@@ -107,10 +105,6 @@ int _lseek_r(struct _reent *r, int file, int ptr, int dir)
int _write_r(struct _reent *r, int file, char * ptr, int len)
{
-#if defined(STDOUT_SD)
- int n;
-#endif
-
(void)r;
(void)file;
(void)ptr;
@@ -119,9 +113,7 @@ int _write_r(struct _reent *r, int file, char * ptr, int len)
__errno_r(r) = EINVAL;
return -1;
}
- n = len;
- while (n--)
- chIOPut(&STDOUT_SD, *ptr++);
+ sdWrite(&STDOUT_SD, (uint8_t *)ptr, (size_t)len);
#endif
return len;
}