git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@1501 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
parent
de95f94fbe
commit
855fe2391d
|
@ -34,7 +34,7 @@
|
|||
* ChibiOS/RT APIs are all named following this convention:
|
||||
* @a ch\<group\>\<action\>\<suffix\>().
|
||||
* The possible groups are: @a Sys, @a Sch, @a Time, @a VT, @a Thd, @a Sem,
|
||||
* @a Mtx, @a Cond, @a Evt, @a Msg, @a IQ, @a OQ, @a IO, @a Dbg,
|
||||
* @a Mtx, @a Cond, @a Evt, @a Msg, @a Stream, @a IO, @a IQ, @a OQ, @a Dbg,
|
||||
* @a Core, @a Heap, @a Pool.
|
||||
*
|
||||
* @section api_suffixes API Names Suffixes
|
||||
|
|
|
@ -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"];
|
||||
|
|
|
@ -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 chIORead()
|
||||
* @see chIOReadTimeout()
|
||||
*/
|
||||
#define sdRead(sdp, b, n) chIQRead(&(sdp)->sd.iqueue, b, n)
|
||||
#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 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 sdGetStatusChangeEventSource(ip) (&((ip)->vmt->sd.sevent))
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -81,6 +81,7 @@
|
|||
#include "threads.h"
|
||||
#include "inline.h"
|
||||
#include "queues.h"
|
||||
#include "streams.h"
|
||||
#include "channels.h"
|
||||
#include "debug.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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_ */
|
||||
|
||||
/** @} */
|
|
@ -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.<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
|
||||
*/
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* @param[in] iqp pointer to an @p InputQueue structure
|
||||
* @param[out] buffer 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.
|
||||
*
|
||||
* 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] 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 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.
|
||||
*
|
||||
* @param[in] oqp pointer to an @p OutputQueue structure
|
||||
* @param[out] buffer pointer to the buffer where the output data is stored
|
||||
* @param[in] n the maximum amount of data to be transferred
|
||||
* @return The number of bytes transferred.
|
||||
*
|
||||
* 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] 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 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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
15
readme.txt
15
readme.txt
|
@ -2,6 +2,21 @@
|
|||
*** Releases ***
|
||||
*****************************************************************************
|
||||
|
||||
*** 1.3.8 ***
|
||||
- NEW: Introduced an abstract streams interface BaseSequentialStream.
|
||||
- NEW: Added timeout specification to the I/O queues read/write primitives.
|
||||
- CHANGE: Modified the BaseChannel interface in order to make it a
|
||||
BaseSequentialStream descendant.
|
||||
- CHANGE: Updated the serial driver model in order to expose the
|
||||
BaseSequentialStream methods.
|
||||
- CHANGE: The behavior of the read/write primitives is changed, now the
|
||||
functions are synchronous and do not return until the specified number of
|
||||
bytes have been transferred or a timeout occurs, the old behavior can be
|
||||
replicated by specifying TIME_IMMEDIATE as timeout. Another difference is
|
||||
that specifying zero as bytes number is like specifying the largest size_t
|
||||
plus one, zero was an illegal value before.
|
||||
- Documentation fixes and improvements, testing strategy explained.
|
||||
|
||||
*** 1.3.7 ***
|
||||
- FIX: Fixed duplicated definition of SPI_USE_MUTUAL_EXCLUSION (bug 2922495).
|
||||
- FIX: Fixed coverage tool hanging during execution (bug 2921120).
|
||||
|
|
|
@ -18,20 +18,52 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* @page testsuite Test Suite
|
||||
* @page testsuite Testing Strategy
|
||||
* <h2>Description</h2>
|
||||
* Most of the ChibiOS/RT demos link a set of software modules (test suite) in
|
||||
* order to verify the proper working of the kernel, the port and the demo
|
||||
* itself.<br>
|
||||
* Each Test Module performs a series of tests on a specified subsystem or
|
||||
* itself.
|
||||
*
|
||||
* <h2>Strategy by Components</h2>
|
||||
* The OS components are tested in various modes depending on their importance:
|
||||
* - <b>Kernel</b>. The kernel code is subject to rigorous testing. The test
|
||||
* suite aims to test <b>all</b> the kernel code and reach a code coverage
|
||||
* as close to 100% as possible. In addition to the code coverage, the kernel
|
||||
* code is tested for <b>functionality</b> and benchmarked for <b>speed</b>
|
||||
* and <b>size</b> before each stable release. In addition to the code
|
||||
* coverage and functional testing a <b>batch compilation test</b> is
|
||||
* performed before each release, the kernel is compiled by alternatively
|
||||
* enabling and disabling all the various configuration options, the
|
||||
* kernel code is expected to compile without errors nor warnings and
|
||||
* execute the test suite without failures (a specific simulator is used
|
||||
* for this execution test, it is done automatically by a script because
|
||||
* the entire sequence can require hours).<br>
|
||||
* All the tests results are included as reports in the OS distribution
|
||||
* under @p ./docs/reports.
|
||||
* - <b>Ports</b>. The port code is tested by executing the kernel test
|
||||
* suite on the target hardware. A port is validated only if it passes all
|
||||
* the tests. Speed and size benchmarks for all the supported architectures
|
||||
* are performed, both size and speed regressions are <b>monitored</b>.
|
||||
* - <b>HAL</b>. The HAL high level code and device drivers implementations
|
||||
* are tested by use in the various demos and/or by users.
|
||||
* - <b>Various</b>. The miscellaneous code is tested by use in the various
|
||||
* demos and/or by users.
|
||||
* - <b>External Code</b>. Not tested, external libraries or components are
|
||||
* used as-is or with minor patching where required, problems are usually
|
||||
* reported upstream.
|
||||
* .
|
||||
* <h2>Kernel Test Suite</h2>
|
||||
* The kernel test suite is divided in modules or test sequences. Each Test
|
||||
* Module performs a series of tests on a specified kernel subsystem or
|
||||
* subsystems and can report a failure/success status and/or a performance
|
||||
* index as the test suite output.<br>
|
||||
* The test suite is usually activated in the demo applications by pressing a
|
||||
* button on the target board, see the readme into the various demos
|
||||
* directories. The test suite output is usually sent through a serial port and
|
||||
* can be examined by using a terminal emulator program.
|
||||
* directories. The test suite output is usually sent through a serial port
|
||||
* and can be examined by using a terminal emulator program.
|
||||
*
|
||||
* <h2>Kernel Test Modules</h2>
|
||||
*
|
||||
* <h2>Test Modules</h2>
|
||||
* - @subpage test_threads
|
||||
* - @subpage test_dynamic
|
||||
* - @subpage test_msg
|
||||
|
|
|
@ -86,6 +86,7 @@ static void queues1_setup(void) {
|
|||
|
||||
static void queues1_execute(void) {
|
||||
unsigned i;
|
||||
size_t n;
|
||||
|
||||
/* Initial empty state */
|
||||
test_assert(1, chIQIsEmpty(&iq), "not empty");
|
||||
|
@ -107,9 +108,8 @@ static void queues1_execute(void) {
|
|||
chIQPutI(&iq, 'A' + i);
|
||||
|
||||
/* Reading the whole thing */
|
||||
test_assert(6,
|
||||
chIQRead(&iq, wa[1], TEST_QUEUES_SIZE * 2) == TEST_QUEUES_SIZE,
|
||||
"wrong returned size");
|
||||
n = chIQReadTimeout(&iq, wa[1], TEST_QUEUES_SIZE * 2, TIME_IMMEDIATE);
|
||||
test_assert(6, n == TEST_QUEUES_SIZE, "wrong returned size");
|
||||
test_assert(7, chIQIsEmpty(&iq), "still full");
|
||||
|
||||
/* Testing reset */
|
||||
|
@ -148,6 +148,7 @@ static void queues2_setup(void) {
|
|||
|
||||
static void queues2_execute(void) {
|
||||
unsigned i;
|
||||
size_t n;
|
||||
|
||||
/* Initial empty state */
|
||||
test_assert(1, chOQIsEmpty(&oq), "not empty");
|
||||
|
@ -165,9 +166,8 @@ static void queues2_execute(void) {
|
|||
test_assert(5, chOQGetI(&oq) == Q_EMPTY, "failed to report Q_EMPTY");
|
||||
|
||||
/* Writing the whole thing */
|
||||
test_assert(6,
|
||||
chOQWrite(&oq, wa[1], TEST_QUEUES_SIZE * 2) == TEST_QUEUES_SIZE,
|
||||
"wrong returned size");
|
||||
n = chOQWriteTimeout(&oq, wa[1], TEST_QUEUES_SIZE * 2, TIME_IMMEDIATE);
|
||||
test_assert(6, n == TEST_QUEUES_SIZE,"wrong returned size");
|
||||
test_assert(7, chOQIsFull(&oq), "not full");
|
||||
|
||||
/* Testing reset */
|
||||
|
|
11
todo.txt
11
todo.txt
|
@ -5,6 +5,7 @@ X = In progress, some work done.
|
|||
* = Done.
|
||||
|
||||
Before 1.4.0:
|
||||
* Abstract streams interface (for MAC, USB endpoints, files, sockets etc).
|
||||
* Abstract I/O channels rather than just serial ports.
|
||||
* Add tests documentation to the general documentation via doxygen.
|
||||
* Static object initializers.
|
||||
|
@ -17,15 +18,16 @@ Before 1.4.0:
|
|||
After 1.4.x
|
||||
- I2C device driver class support.
|
||||
- USB device support.
|
||||
- Abstract streams interface (for MAC and USB endpoints).
|
||||
- Remove any instance of unnamed structures/unions.
|
||||
- MAC driver revision in order to support copy-less operations, this will
|
||||
require changes to lwIP or a new TCP/IP stack however.
|
||||
- Objects registry in the kernel.
|
||||
- OSEK-style simple tasks within the idle thread.
|
||||
- Code examples into the documentation.
|
||||
- Update C++ wrapper (Heap, Pools, Mailboxes and any new feature).
|
||||
- Threads Pools manager in the library.
|
||||
? Minimal optional C-runtime library (complete enough for lwIP).
|
||||
? Think to something for threads restart.
|
||||
- Update C++ wrapper (Heap, Pools, Mailboxes and any new feature).
|
||||
? Remove any instance of unnamed structures/unions.
|
||||
|
||||
Ideas for 2.x.x:
|
||||
- High resolution timers and tickless kernel.
|
||||
|
@ -40,7 +42,7 @@ Side projects:
|
|||
* FatFS library integration and demo.
|
||||
X ChibiOS Wizard, UML modeling and ChibiOS applications code and
|
||||
documentation generator.
|
||||
X OSEK layer.
|
||||
? OSEK layer.
|
||||
- Posix layer.
|
||||
X File System
|
||||
- Visual debugger/monitor interfaced through OpenOCD.
|
||||
|
@ -48,3 +50,4 @@ X File System
|
|||
Lower priority:
|
||||
- More demos
|
||||
- More ports
|
||||
- More compilers.
|
||||
|
|
Loading…
Reference in New Issue