Added Javadoc to fifo module and header file.

This commit is contained in:
skarg
2013-02-22 16:19:42 +00:00
parent 2eb8e84f41
commit 7084b9f036
2 changed files with 274 additions and 210 deletions
+35 -55
View File
@@ -1,92 +1,72 @@
/**************************************************************************
*
* Copyright (C) 2012 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*********************************************************************/
/**
* @file
* @author Steve Karg
* @date 2004
*/
#ifndef FIFO_H
#define FIFO_H
/* Functional Description: Generic FIFO library for deeply
embedded system. See the unit tests for usage examples.
This library only uses a byte sized chunk.
This library is designed for use in Interrupt Service Routines
and so is declared as "static inline" */
#include <stdint.h>
#include <stdbool.h>
/**
* FIFO data structure
*
* @{
*/
struct fifo_buffer_t {
volatile unsigned head; /* first byte of data */
volatile unsigned tail; /* last byte of data */
volatile uint8_t *buffer; /* block of memory or array of data */
unsigned buffer_len; /* length of the data */
/** first byte of data */
volatile unsigned head;
/** last byte of data */
volatile unsigned tail;
/** block of memory or array of data */
volatile uint8_t *buffer;
/** length of the data */
unsigned buffer_len;
};
typedef struct fifo_buffer_t FIFO_BUFFER;
/** @} */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
unsigned FIFO_Count(
FIFO_BUFFER const *b);
unsigned FIFO_Count(FIFO_BUFFER const *b);
bool FIFO_Full(
FIFO_BUFFER const *b);
bool FIFO_Full(FIFO_BUFFER const *b);
bool FIFO_Available(
FIFO_BUFFER const *b,
bool FIFO_Available(FIFO_BUFFER const *b,
unsigned count);
bool FIFO_Empty(
FIFO_BUFFER const *b);
bool FIFO_Empty(FIFO_BUFFER const *b);
uint8_t FIFO_Peek(
FIFO_BUFFER const *b);
uint8_t FIFO_Peek(FIFO_BUFFER const *b);
uint8_t FIFO_Get(
FIFO_BUFFER * b);
uint8_t FIFO_Get(FIFO_BUFFER * b);
unsigned FIFO_Pull(
FIFO_BUFFER * b,
unsigned FIFO_Pull(FIFO_BUFFER * b,
uint8_t * data_bytes,
unsigned length);
bool FIFO_Put(
FIFO_BUFFER * b,
bool FIFO_Put(FIFO_BUFFER * b,
uint8_t data_byte);
bool FIFO_Add(
FIFO_BUFFER * b,
bool FIFO_Add(FIFO_BUFFER * b,
uint8_t * data_bytes,
unsigned count);
void FIFO_Flush(
FIFO_BUFFER * b);
void FIFO_Flush(FIFO_BUFFER * b);
/* note: buffer_len must be a power of two */
void FIFO_Init(
FIFO_BUFFER * b,
void FIFO_Init(FIFO_BUFFER * b,
volatile uint8_t * buffer,
unsigned buffer_len);
#ifdef TEST
#include "ctest.h"
void testFIFOBuffer(Test * pTest);
#endif
#ifdef __cplusplus
}
#endif /* __cplusplus */
+239 -155
View File
@@ -1,56 +1,107 @@
/*####COPYRIGHTBEGIN####
-------------------------------------------
Copyright (C) 2004 by Steve Karg
This program 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 2
of the License, or (at your option) any later version.
This program 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, write to:
The Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307
USA.
As a special exception, if other files instantiate templates or
use macros or inline functions from this file, or you compile
this file and link it with other works to produce a work based
on this file, this file does not by itself cause the resulting
work to be covered by the GNU General Public License. However
the source code for this file must still be made available in
accordance with section (3) of the GNU General Public License.
This exception does not invalidate any other reasons why a work
based on this file might be covered by the GNU General Public
License.
-------------------------------------------
####COPYRIGHTEND####*/
/** @file fifo.c Generic FIFO library for deeply embedded system */
/* Functional Description: Generic FIFO library for deeply
embedded system. See the unit tests for usage examples. */
/**
* @file
* @author Steve Karg
* @date 2004
* @brief Generic interrupt safe FIFO library for deeply embedded system.
*
* @section LICENSE
*
* This program 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 2
* of the License, or (at your option) any later version.
*
* This program 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, write to:
* The Free Software Foundation, Inc.
* 59 Temple Place - Suite 330
* Boston, MA 02111-1307
* USA.
*
* As a special exception, if other files instantiate templates or
* use macros or inline functions from this file, or you compile
* this file and link it with other works to produce a work based
* on this file, this file does not by itself cause the resulting
* work to be covered by the GNU General Public License. However
* the source code for this file must still be made available in
* accordance with section (3) of the GNU General Public License.
*
* This exception does not invalidate any other reasons why a work
* based on this file might be covered by the GNU General Public
* License.
*
* @section DESCRIPTION
*
* Generic interrupt safe FIFO library for deeply embedded system
* This library only uses a byte sized chunk for a data element.
* It uses a data store whose size is a power of 2 (8, 16, 32, 64, ...)
* and doesn't waste any data bytes. It has very low overhead, and
* utilizes modulo for indexing the data in the data store.
*
* To use this library, first declare a data store, sized for a power of 2:
* {@code
* static volatile uint8_t data_store[64];
* }
*
* Then declare the FIFO tracking structure:
* {@code
* static FIFO_BUFFER queue;
* }
*
* Initialize the queue with the data store:
* {@code
* FIFO_Init(&queue, data_store, sizeof(data_store));
* }
*
* Then begin to use the FIFO queue by giving it data, retreiving data,
* and checking the FIFO queue to see if it is empty or full:
* {@code
* uint8_t in_data = 0;
* uint8_t out_data = 0;
* uint8_t add_data[5] = {0};
* uint8_t pull_data[5] = {0};
* unsigned count = 0;
* bool status = false;
*
* status = FIFO_Put(&queue, in_data);
* if (!FIFO_Empty(&queue)) {
* out_data = FIFO_Get(&queue);
* }
* if (FIFO_Available(&queue, sizeof(add_data))) {
* status = FIFO_Add(&queue, add_data, sizeof(add_data));
* }
* count = FIFO_Count(&queue);
* if (count == sizeof(add_data)) {
* count = FIFO_Pull(&queue, &pull_data[0], sizeof(pull_data));
* }
*
* }
*
* Normally the FIFO is used by a producer, such as in interrupt service
* routine, which places data into the queue using FIFO_Put(), and a consumer,
* such as a main loop handler, which pulls data from the queue by first
* checking the queue for data using FIFO_Empty(), and then pulling data from
* the queue using FIFO_Get().
*
*/
#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
#include "fifo.h"
/****************************************************************************
* DESCRIPTION: Returns the number of elements in the ring buffer
* RETURN: Number of elements in the ring buffer
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
unsigned FIFO_Count(
FIFO_BUFFER const *b)
/**
* Returns the number of bytes in the FIFO
*
* @param b - pointer to FIFO_BUFFER structure
*
* @return Number of bytes in the FIFO
*/
unsigned FIFO_Count(FIFO_BUFFER const *b)
{
unsigned head, tail; /* used to avoid volatile decision */
@@ -63,91 +114,106 @@ unsigned FIFO_Count(
}
}
/****************************************************************************
* DESCRIPTION: Returns the empty/full status of the ring buffer
* RETURN: true if the ring buffer is full, false if it is not.
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
bool FIFO_Full(
FIFO_BUFFER const *b)
/**
* Returns the full status of the FIFO
*
* @param b - pointer to FIFO_BUFFER structure
*
* @return true if the FIFO is full, false if it is not.
*/
bool FIFO_Full(FIFO_BUFFER const *b)
{
return (b ? (FIFO_Count(b) == b->buffer_len) : true);
}
/****************************************************************************
* DESCRIPTION: Tests to see if space is available
* RETURN: true if the number of bytes is available
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
bool FIFO_Available(
FIFO_BUFFER const *b,
/**
* Tests to see if space is available in the FIFO
*
* @param b - pointer to FIFO_BUFFER structure
* @param count [in] - number of bytes tested for availability
*
* @return true if the number of bytes sought is available
*/
bool FIFO_Available(FIFO_BUFFER const *b,
unsigned count)
{
return (b ? (count <= (b->buffer_len - FIFO_Count(b))) : false);
}
/****************************************************************************
* DESCRIPTION: Returns the empty/full status of the ring buffer
* RETURN: true if the ring buffer is empty, false if it is not.
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
bool FIFO_Empty(
FIFO_BUFFER const *b)
/**
* Returns the empty status of the FIFO
*
* @param b - pointer to FIFO_BUFFER structure
* @return true if the FIFO is empty, false if it is not.
*/
bool FIFO_Empty(FIFO_BUFFER const *b)
{
return (b ? (FIFO_Count(b) == 0) : true);
}
/****************************************************************************
* DESCRIPTION: Looks at the data from the head of the list without removing it
* RETURN: byte of data, or zero if nothing in the list
* ALGORITHM: none
* NOTES: Use Empty function to see if there is data to retrieve
*****************************************************************************/
uint8_t FIFO_Peek(
FIFO_BUFFER const *b)
/**
* Peeks at the data from the front of the FIFO without removing it.
* Use FIFO_Empty() or FIFO_Available() function to see if there is
* data to retrieve since this function doesn't return a flag indicating
* success or failure.
*
* @param b - pointer to FIFO_BUFFER structure
*
* @return byte of data, or zero if nothing in the list
*/
uint8_t FIFO_Peek(FIFO_BUFFER const *b)
{
unsigned index;
if (b) {
return (b->buffer[b->tail % b->buffer_len]);
index = b->tail % b->buffer_len;
return (b->buffer[index]);
}
return 0;
}
/****************************************************************************
* DESCRIPTION: Gets the data from the front of the list, and removes it
* RETURN: the data, or zero if nothing in the list
* ALGORITHM: none
* NOTES: Use Empty function to see if there is data to retrieve
*****************************************************************************/
uint8_t FIFO_Get(
FIFO_BUFFER * b)
/**
* Gets a byte from the front of the FIFO, and removes it.
* Use FIFO_Empty() or FIFO_Available() function to see if there is
* data to retrieve since this function doesn't return a flag indicating
* success or failure.
*
* @param b - pointer to FIFO_BUFFER structure
*
* @return the data
*/
uint8_t FIFO_Get(FIFO_BUFFER * b)
{
uint8_t data_byte = 0;
unsigned index;
if (!FIFO_Empty(b)) {
data_byte = b->buffer[b->tail % b->buffer_len];
index = b->tail % b->buffer_len;
data_byte = b->buffer[index];
b->tail++;
}
return data_byte;
}
/****************************************************************************
* DESCRIPTION: Pulls the data from the front of the list, and removes it
* RETURN: the data (in parameter) and the number of bytes pulled
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
unsigned FIFO_Pull(
FIFO_BUFFER * b,
uint8_t * data_bytes,
/**
* Pulls one or more bytes from the front of the FIFO, and removes them
* from the FIFO. If less bytes are available, only the available bytes
* are retrieved.
*
* @param b - pointer to FIFO_BUFFER structure
* @param buffer [out] - buffer to hold the pulled bytes
* @param length [in] - number of bytes to pull from the FIFO
*
* @return the number of bytes actually pulled from the FIFO
*/
unsigned FIFO_Pull(FIFO_BUFFER * b,
uint8_t * buffer,
unsigned length)
{
unsigned count;
uint8_t data_byte;
unsigned index;
count = FIFO_Count(b);
if (count > length) {
@@ -159,32 +225,38 @@ unsigned FIFO_Pull(
length = count;
}
while (count) {
data_byte = b->buffer[b->tail % b->buffer_len];
index = b->tail % b->buffer_len;
data_byte = b->buffer[index];
b->tail++;
*data_bytes = data_byte;
data_bytes++;
if (buffer) {
*buffer = data_byte;
buffer++;
}
count--;
}
return length;
}
/****************************************************************************
* DESCRIPTION: Adds an element of data to the FIFO
* RETURN: true on successful add, false if not added
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
bool FIFO_Put(
FIFO_BUFFER * b,
/**
* Adds a byte of data to the FIFO
*
* @param b - pointer to FIFO_BUFFER structure
* @param data_byte [in] - data to put into the FIFO
*
* @return true on successful add, false if not added
*/
bool FIFO_Put(FIFO_BUFFER * b,
uint8_t data_byte)
{
bool status = false; /* return value */
unsigned index;
if (b) {
/* limit the ring to prevent overwriting */
/* limit the buffer to prevent overwriting */
if (!FIFO_Full(b)) {
b->buffer[b->head % b->buffer_len] = data_byte;
index = b->head % b->buffer_len;
b->buffer[index] = data_byte;
b->head++;
status = true;
}
@@ -193,25 +265,29 @@ bool FIFO_Put(
return status;
}
/****************************************************************************
* DESCRIPTION: Adds one or more elements of data to the FIFO
* RETURN: true if space available and added, false if not added
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
bool FIFO_Add(
FIFO_BUFFER * b,
uint8_t * data_bytes,
/**
* Adds one or more bytes of data to the FIFO
*
* @param b - pointer to FIFO_BUFFER structure
* @param buffer [out] - data bytes to add to the FIFO
* @param count [in] - number of bytes to add to the FIFO
*
* @return true if space available and added, false if not added
*/
bool FIFO_Add(FIFO_BUFFER * b,
uint8_t * buffer,
unsigned count)
{
bool status = false; /* return value */
unsigned index;
/* limit the ring to prevent overwriting */
if (FIFO_Available(b, count)) {
/* limit the buffer to prevent overwriting */
if (FIFO_Available(b, count) && buffer) {
while (count) {
b->buffer[b->head % b->buffer_len] = *data_bytes;
index = b->head % b->buffer_len;
b->buffer[index] = *buffer;
b->head++;
data_bytes++;
buffer++;
count--;
}
status = true;
@@ -220,14 +296,14 @@ bool FIFO_Add(
return status;
}
/****************************************************************************
* DESCRIPTION: Flushes any data in the buffer
* RETURN: none
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
void FIFO_Flush(
FIFO_BUFFER * b)
/**
* Flushes any data in the FIFO buffer
*
* @param b - pointer to FIFO_BUFFER structure
*
* @return none
*/
void FIFO_Flush(FIFO_BUFFER * b)
{
unsigned head; /* used to avoid volatile decision */
@@ -237,18 +313,20 @@ void FIFO_Flush(
}
}
/****************************************************************************
* DESCRIPTION: Configures the ring buffer
* RETURN: none
* ALGORITHM: none
* NOTES: buffer_len must be a power of two
*****************************************************************************/
void FIFO_Init(
FIFO_BUFFER * b,
/**
* Initializes the FIFO buffer with a data store
*
* @param b - pointer to FIFO_BUFFER structure
* @param buffer [in] - data bytes used to store bytes used by the FIFO
* @param buffer_len [in] - size of the buffer in bytes - must be power of 2.
*
* @return none
*/
void FIFO_Init(FIFO_BUFFER * b,
volatile uint8_t * buffer,
unsigned buffer_len)
{
if (b) {
if (b && buffer && buffer_len) {
b->head = 0;
b->tail = 0;
b->buffer = buffer;
@@ -262,17 +340,19 @@ void FIFO_Init(
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include "ctest.h"
/* test the FIFO */
/* note: must be a power of two! */
#define FIFO_BUFFER_SIZE 64
void testFIFOBuffer(
Test * pTest)
/**
* Unit Test for the FIFO buffer
*
* @param pTest - test tracking pointer
*/
void testFIFOBuffer(Test * pTest)
{
/* FIFO data structure */
FIFO_BUFFER test_buffer = { 0 };
volatile uint8_t data_store[FIFO_BUFFER_SIZE] = { 0 };
/* FIFO data store. Note: size must be a power of two! */
volatile uint8_t data_store[64] = { 0 };
uint8_t add_data[40] = { "RoseSteveLouPatRachelJessicaDaniAmyHerb" };
uint8_t test_add_data[40] = { 0 };
uint8_t test_data = 0;
@@ -284,7 +364,7 @@ void testFIFOBuffer(
ct_test(pTest, FIFO_Empty(&test_buffer));
/* load the buffer */
for (test_data = 0; test_data < FIFO_BUFFER_SIZE; test_data++) {
for (test_data = 0; test_data < sizeof(data_store); test_data++) {
ct_test(pTest, !FIFO_Full(&test_buffer));
ct_test(pTest, FIFO_Available(&test_buffer, 1));
status = FIFO_Put(&test_buffer, test_data);
@@ -297,7 +377,7 @@ void testFIFOBuffer(
status = FIFO_Put(&test_buffer, 42);
ct_test(pTest, status == false);
/* unload the buffer */
for (index = 0; index < FIFO_BUFFER_SIZE; index++) {
for (index = 0; index < sizeof(data_store); index++) {
ct_test(pTest, !FIFO_Empty(&test_buffer));
test_data = FIFO_Peek(&test_buffer);
ct_test(pTest, test_data == index);
@@ -313,7 +393,7 @@ void testFIFOBuffer(
ct_test(pTest, test_data == 0);
ct_test(pTest, FIFO_Empty(&test_buffer));
/* test the ring around the buffer */
for (index = 0; index < FIFO_BUFFER_SIZE; index++) {
for (index = 0; index < sizeof(data_store); index++) {
ct_test(pTest, FIFO_Empty(&test_buffer));
ct_test(pTest, FIFO_Available(&test_buffer, 4));
for (count = 1; count < 4; count++) {
@@ -381,8 +461,12 @@ void testFIFOBuffer(
}
#ifdef TEST_FIFO_BUFFER
int main(
void)
/**
* Main program entry for Unit Test
*
* @return returns 0 on success, and non-zero on fail.
*/
int main(void)
{
Test *pTest;
bool rc;