From 855fe2391d07c5dab27129ad626541482fe8d782 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Tue, 5 Jan 2010 17:14:09 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@1501 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/hal.dox | 12 ++-- os/hal/include/serial.h | 83 +++++++++++++++++++++---- os/hal/src/serial.c | 31 ++++++--- os/kernel/include/ch.h | 1 + os/kernel/include/channels.h | 127 +++++++++++++++++++++++-------------- os/kernel/include/queues.h | 14 +++-- os/kernel/include/streams.h | 106 +++++++++++++++++++++++++++++++ os/kernel/kernel.dox | 31 ++++++--- os/kernel/src/chqueues.c | 145 ++++++++++++++++++++++--------------------- os/various/syscalls.c | 12 +--- 10 files changed, 394 insertions(+), 168 deletions(-) create mode 100644 os/kernel/include/streams.h (limited to 'os') 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 (HLD). This layer contains the definitions * of the driver's APIs and the platform independent part of the driver.
* An HLD is composed by two files: - * - @.c, the high level implementation file. This file must be + * - @.c, the HLD implementation file. This file must be * included in the Makefile in order to use the driver. - * - @.h, the high level header file. This file must be included - * by the application code in order to access the driver's APIs. + * - @.h, the HLD header file. This file is implicitly + * included by the HAL header file @p hal.h. * . * - Low Level Device Driver (LLD). This layer contains the platform * dependent part of the driver.
* A LLD is composed by two files: - * - @_lld.c, the low level implementation file. This file must be + * - @_lld.c, the LLD implementation file. This file must be * included in the Makefile in order to use the driver. - * - @_lld.h, the high level header file. This file is implicitly + * - @_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 @@ -107,6 +107,10 @@ struct _serial_driver_methods { * @brief @p SerialDriver virtual methods table. */ struct SerialDriverVMT { + /** + * @p BaseSequentialStream class inherited methods. + */ + struct _base_sequental_stream_methods bss; /** * @p BaseChannel class inherited methods. */ @@ -133,6 +137,10 @@ struct _SerialDriver { * Virtual Methods Table. */ const struct SerialDriverVMT *vmt; + /** + * @p BaseSequentialStream class inherited data. + */ + struct _base_sequental_stream_data bss; /** * @p BaseChannel class inherited data. */ @@ -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. @@ -207,23 +213,78 @@ 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); }; /** @@ -65,6 +75,10 @@ struct _base_channel_data { * @brief @p BaseChannel virtual methods table. */ struct BaseChannelVMT { + /** + * @p BaseSequentialStream class inherited methods. + */ + struct _base_sequental_stream_methods bss; /** * @p BaseChannel class specific methods. */ @@ -72,14 +86,21 @@ struct BaseChannelVMT { }; /** + * @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 { /** * Virtual Methods Table. */ const struct BaseChannelVMT *vmt; + /** + * @p BaseSequentialStream class inherited data. + */ + struct _base_sequental_stream_data bss; /** * @p BaseChannel class specific data. */ @@ -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); }; /** @@ -207,6 +256,10 @@ struct _base_asynchronous_channel_data { * @brief @p BaseAsynchronousChannel virtual methods table. */ struct BaseAsynchronousChannelVMT { + /** + * @p BaseSequentialStream class inherited methods. + */ + struct _base_sequental_stream_methods bss; /** * @p BaseChannel class inherited methods. */ @@ -221,14 +274,18 @@ 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 { /** * Virtual Methods Table. */ const struct BaseAsynchronousChannelVMT *vmt; + /** + * @p BaseSequentialStream class inherited data. + */ + struct _base_sequental_stream_data bss; /** * @p BaseChannel class inherited data. */ @@ -239,32 +296,6 @@ typedef struct { struct _base_asynchronous_channel_data bac; } 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 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 . +*/ + +/** + * @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 @@ -282,18 +282,31 @@ * @ingroup kernel */ +/** + * @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.
+ * 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.
+ * @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.
* 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.
+ * 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 for each 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 for each 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; } -- cgit v1.2.3