1cbd89d4a96336f58c1405856b9742cfce8737e1
[bertos.git] / mware / fifobuf.h
1 /*!
2  * \file
3  * <!--
4  * Copyright (C) 2003,2004 Develer S.r.l. (http://www.develer.com/)
5  * Copyright (C) 2001 Bernardo Innocenti <bernie@develer.com>
6  * All Rights Reserved.
7  * -->
8  *
9  * \version $Id$
10  *
11  * \author Bernardo Innocenti <bernie@develer.com>
12  *
13  * \brief General pourpose FIFO buffer implemented with a ring buffer
14  *
15  * \li \c begin punta al primo elemento del buffer,
16  * \li \c end punta all'ultimo elemento,
17  * \li \c head punta al prossimo elemento che verra' estratto,
18  * \li \c tail punta alla posizione successiva all'ultimo elemento inserito.
19  * \li quando uno dei due puntatori raggiunge @c end, viene resettato a @c begin.
20  *
21  * <pre>
22  *
23  *  +-----------------------------------+
24  *  |  vuoto  |   dati validi  |  vuoto |
25  *  +-----------------------------------+
26  *  ^         ^                ^        ^
27  *  begin    head             tail     end
28  *
29  * </pre>
30  *
31  * Il buffer e' VUOTO quando head e tail coincidono:
32  *              \code head == tail \endcode
33  *
34  * Il buffer e' PIENO quando tail si trova immediatamente dietro a head:
35  *              \code tail == head - 1 \endcode
36  *
37  * Il buffer e' PIENO anche quando tail e' posizionato
38  * sull'ultima posizione del buffer e head sulla prima:
39  *              \code head == begin && tail == end \endcode
40  */
41
42 /*
43  * $Log$
44  * Revision 1.1  2004/05/23 15:43:16  bernie
45  * Import mware modules.
46  *
47  * Revision 1.3  2004/05/22 17:55:58  rasky
48  * \samp non esiste in doxygen
49  *
50  * Revision 1.2  2004/04/27 11:13:29  rasky
51  * Spostate tutte le definizioni CPU-specific da compiler.h nel nuovo file cpu.h
52  *
53  * Revision 1.1  2004/04/21 17:38:25  rasky
54  * New application
55  *
56  * Revision 1.4  2004/03/24 15:37:03  bernie
57  * Remove Copyright messages from Doxygen output
58  *
59  * Revision 1.3  2004/03/18 18:11:07  bernie
60  * Add thread-safe FIFO handling macros
61  *
62  * Revision 1.2  2004/03/01 08:00:36  bernie
63  * Fixes for Doxygen
64  *
65  * Revision 1.1  2003/12/07 04:04:20  bernie
66  * Initial project_ks framework.
67  *
68  * Revision 1.1  2003/11/21 16:36:17  aleph
69  * Rename from fifo to fifobuf to avoid conflict with BSP fifo.h header
70  *
71  * Revision 1.1  2003/11/20 22:17:41  aleph
72  * Add fifo buffer used by serial
73  *
74  */
75
76 #ifndef MWARE_FIFO_H
77 #define MWARE_FIFO_H
78
79 #include "cpu.h"
80 #ifndef COMPILER_H
81 #include "compiler.h"
82 #endif
83
84 typedef struct FIFOBuffer
85 {
86         unsigned char *head;
87         unsigned char *tail;
88         unsigned char *begin;
89         unsigned char *end;
90 } FIFOBuffer;
91
92 /* Public function prototypes */
93 void fifo_init(volatile FIFOBuffer *fb, unsigned char *buf, size_t size);
94
95 #pragma interrupt called
96 void fifo_push(volatile FIFOBuffer *fb, unsigned char c);
97
98 #pragma interrupt called
99 unsigned char fifo_pop(volatile FIFOBuffer *fb);
100
101
102 /*!
103  * Check whether the fifo is empty
104  *
105  * \note Calling fifo_isempty() is safe while a concurrent
106  *       execution context is calling fifo_push() or fifo_pop()
107  *       only if the CPU can atomically update a pointer.
108  */
109 #define fifo_isempty(fb)        ((fb)->head == (fb)->tail)
110
111 /*!
112  * Check whether the fifo is full
113  *
114  * \note Calling fifo_isfull() is safe while a concurrent
115  *       execution context is calling fifo_pop() and the
116  *       CPU can update a pointer atomically.
117  *       It is NOT safe when the other context calls
118  *       fifo_push().
119  *       This limitation is not usually problematic in a
120  *       consumer/producer scenario because the
121  *       fifo_isfull() and fifo_push() are usually called
122  *       in the producer context.
123  */
124 #define fifo_isfull(fb) \
125         ((((fb)->head == (fb)->begin) && ((fb)->tail == (fb)->end)) \
126         || ((fb)->tail == (fb)->head - 1))
127
128 /*!
129  * Make the fifo empty, discarding all its current contents.
130  */
131 #define fifo_flush(fb)  ((fb)->head = (fb)->tail)
132
133 #if !defined(__AVR__)
134
135         /* No tricks needed on 16/32bit CPUs */
136 #       define fifo_isempty_locked(fb) fifo_isempty((fb))
137
138 #else /* !__AVR__ */
139
140         INLINE bool fifo_isempty_locked(const volatile FIFOBuffer *_fb);
141         INLINE bool fifo_isempty_locked(const volatile FIFOBuffer *_fb)
142         {
143                 bool _result;
144                 cpuflags_t _flags;
145
146                 DISABLE_IRQSAVE(_flags);
147                 _result = fifo_isempty(_fb);
148                 ENABLE_IRQRESTORE(_flags);
149
150                 return _result;
151         }
152
153 #endif /* !__AVR__ */
154
155 /*!
156  * Thread safe version of fifo_isfull()
157  */
158 INLINE bool fifo_isfull_locked(const volatile FIFOBuffer *_fb);
159 INLINE bool fifo_isfull_locked(const volatile FIFOBuffer *_fb)
160 {
161         bool _result;
162         cpuflags_t _flags;
163
164         DISABLE_IRQSAVE(_flags);
165         _result = fifo_isfull(_fb);
166         ENABLE_IRQRESTORE(_flags);
167
168         return _result;
169 }
170
171 #endif /* MWARE_FIFOBUF_H */
172