-/*!
+/**
* \file
* <!--
* Copyright 2003, 2004 Develer S.r.l. (http://www.develer.com/)
* Copyright 2001 Bernardo Innocenti <bernie@develer.com>
- * This file is part of DevLib - See devlib/README for information.
+ * This file is part of DevLib - See README.devlib for information.
* -->
*
* \version $Id$
/*#*
*#* $Log$
+ *#* Revision 1.22 2006/07/19 12:56:27 bernie
+ *#* Convert to new Doxygen style.
+ *#*
+ *#* Revision 1.21 2005/11/04 16:20:02 bernie
+ *#* Fix reference to README.devlib in header.
+ *#*
+ *#* Revision 1.20 2005/04/11 19:10:28 bernie
+ *#* Include top-level headers from cfg/ subdir.
+ *#*
+ *#* Revision 1.19 2004/12/08 08:30:12 bernie
+ *#* Add missing header.
+ *#*
+ *#* Revision 1.18 2004/11/16 21:55:12 bernie
+ *#* Workaround for a known fifobuf bug.
+ *#*
+ *#* Revision 1.17 2004/09/14 20:57:00 bernie
+ *#* Use debug.h instead of kdebug.h.
+ *#*
+ *#* Revision 1.16 2004/09/06 21:39:08 bernie
+ *#* Simplify code using ATOMIC().
+ *#*
*#* Revision 1.15 2004/08/29 22:05:16 bernie
*#* Rename BITS_PER_PTR to CPU_BITS_PER_PTR.
*#*
#ifndef MWARE_FIFO_H
#define MWARE_FIFO_H
-#include "cpu.h"
+#include <cfg/cpu.h>
+#include <cfg/debug.h>
typedef struct FIFOBuffer
{
} FIFOBuffer;
-/*!
+#define ASSERT_VALID_FIFO(fifo) \
+ ATOMIC( \
+ ASSERT((fifo)->head >= (fifo)->begin); \
+ ASSERT((fifo)->head <= (fifo)->end); \
+ ASSERT((fifo)->tail >= (fifo)->begin); \
+ ASSERT((fifo)->tail <= (fifo)->end); \
+ )
+
+
+/**
* Check whether the fifo is empty
*
* \note Calling fifo_isempty() is safe while a concurrent
*/
INLINE bool fifo_isempty(const FIFOBuffer *fb)
{
+ //ASSERT_VALID_FIFO(fb);
return fb->head == fb->tail;
}
-/*!
+/**
* Check whether the fifo is full
*
* \note Calling fifo_isfull() is safe while a concurrent
*/
INLINE bool fifo_isfull(const FIFOBuffer *fb)
{
+ //ASSERT_VALID_FIFO(fb);
return
((fb->head == fb->begin) && (fb->tail == fb->end))
|| (fb->tail == fb->head - 1);
}
-/*!
+/**
* Pop a character from the fifo buffer.
*
* \note Calling \c fifo_push() on a full buffer is undefined.
#ifdef __MWERKS__
#pragma interrupt called
#endif
+ //ASSERT_VALID_FIFO(fb);
+
/* Write at tail position */
*(fb->tail) = c;
- if (fb->tail == fb->end)
+ if (UNLIKELY(fb->tail == fb->end))
/* wrap tail around */
fb->tail = fb->begin;
else
}
-/*!
+/**
* Pop a character from the fifo buffer.
*
* \note Calling \c fifo_pop() on an empty buffer is undefined.
#ifdef __MWERKS__
#pragma interrupt called
#endif
- if (fb->head == fb->end)
+ //ASSERT_VALID_FIFO(fb);
+
+ if (UNLIKELY(fb->head == fb->end))
{
/* wrap head around */
fb->head = fb->begin;
}
-/*!
+/**
* Make the fifo empty, discarding all its current contents.
*/
INLINE void fifo_flush(FIFOBuffer *fb)
{
+ //ASSERT_VALID_FIFO(fb);
fb->head = fb->tail;
}
*/
#define fifo_isempty_locked(fb) fifo_isempty((fb))
#define fifo_push_locked(fb, c) fifo_push((fb), (c))
- #define fifo_flush_locked(fb) fifo_flush((fb))
+ #define fifo_pop_locked(fb) fifo_pop((fb))
+ #define fifo_flush_locked(fb) fifo_flush((fb))
#else /* CPU_REG_BITS < CPU_BITS_PER_PTR */
- /*!
+ /**
* Similar to fifo_isempty(), but with stronger guarantees for
* concurrent access between user and interrupt code.
*
INLINE bool fifo_isempty_locked(const FIFOBuffer *fb)
{
bool result;
- cpuflags_t flags;
-
- DISABLE_IRQSAVE(flags);
- result = fifo_isempty(fb);
- ENABLE_IRQRESTORE(flags);
-
+ ATOMIC(result = fifo_isempty(fb));
return result;
}
- /*!
+ /**
* Similar to fifo_push(), but with stronger guarantees for
* concurrent access between user and interrupt code.
*
*/
INLINE void fifo_push_locked(FIFOBuffer *fb, unsigned char c)
{
- cpuflags_t flags;
- DISABLE_IRQSAVE(flags);
- fifo_push(fb, c);
- ENABLE_IRQRESTORE(flags);
+ ATOMIC(fifo_push(fb, c));
}
+ /* Probably not really needed, but hard to prove. */
+ INLINE unsigned char fifo_pop_locked(FIFOBuffer *fb)
+ {
+ unsigned char c;
+ ATOMIC(c = fifo_pop(fb));
+ return c;
+ }
- /*!
+ /**
* Similar to fifo_flush(), but with stronger guarantees for
* concurrent access between user and interrupt code.
*
*/
INLINE void fifo_flush_locked(FIFOBuffer *fb)
{
- cpuflags_t flags;
- DISABLE_IRQSAVE(flags);
- fifo_flush(fb);
- ENABLE_IRQRESTORE(flags);
+ ATOMIC(fifo_flush(fb));
}
#endif /* CPU_REG_BITS < BITS_PER_PTR */
-/*!
+/**
* Thread safe version of fifo_isfull()
*/
INLINE bool fifo_isfull_locked(const FIFOBuffer *_fb)
{
- bool _result;
- cpuflags_t _flags;
-
- DISABLE_IRQSAVE(_flags);
- _result = fifo_isfull(_fb);
- ENABLE_IRQRESTORE(_flags);
-
- return _result;
+ bool result;
+ ATOMIC(result = fifo_isfull(_fb));
+ return result;
}
-/*!
+/**
* FIFO Initialization.
*/
INLINE void fifo_init(FIFOBuffer *fb, unsigned char *buf, size_t size)
{
+ /* FIFO buffers have a known bug with 1-byte buffers. */
+ ASSERT(size > 1);
+
fb->head = fb->tail = fb->begin = buf;
fb->end = buf + size - 1;
}