iLLD_TC27xD  1.0
Ifx_Fifo.c
Go to the documentation of this file.
1 /**
2  * \file Ifx_Fifo.c
3  * \brief FIFO functions
4  *
5  * \version iLLD_1_0_0_11_0
6  * \copyright Copyright (c) 2013 Infineon Technologies AG. All rights reserved.
7  *
8  *
9  * IMPORTANT NOTICE
10  *
11  *
12  * Infineon Technologies AG (Infineon) is supplying this file for use
13  * exclusively with Infineon's microcontroller products. This file can be freely
14  * distributed within development tools that are supporting such microcontroller
15  * products.
16  *
17  * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
18  * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
20  * INFINEON SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
21  * OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
22  *
23  */
24 
25 //------------------------------------------------------------------------------
26 #include "Ifx_Fifo.h"
27 #include <stdlib.h>
28 #include "Ifx_CircularBuffer.h"
29 #include "_Utilities/Ifx_Assert.h"
30 #include "Cpu/Std/IfxCpu.h"
31 #include "SysSe/Bsp/Bsp.h"
32 //------------------------------------------------------------------------------
33 /*
34  * Note: the fifo function can be used to exchange data between the main task and interrupts:
35  * - a mutex using the interrupt enable / disable is implemented to insure
36  * data consitancy
37  * - it is supposed that all access to 8, 16, 32 bit data are atomic and are
38  * therefore not protected by a critical section
39  * - the following is possible
40  * reader(main) -- writer(main)
41  * reader(main) -- writer(interrupt)
42  * reader(interrupt) -- writer(main)
43  * reader(interrupt) -- writer(interrupt)
44  * - Only one reader and one writer are allowed by FIFO, no nested read write
45  * Implementation note: as an interrupt runs at a higher cpu level than the thread
46  * the interrupt is not disabled in the IntfifoXXX() functions
47  * This is valid is an OS is used.
48  *
49  */
50 //------------------------------------------------------------------------------
52 {
53  Ifx_Fifo *fifo = NULL_PTR;
54 
55  size = Ifx_AlignOn32(size); /* data transfer is optimised for 32 bit access */
56 
57  fifo = malloc(size + sizeof(Ifx_Fifo) + 8); /* +8 because of padding in case the pointer is not aligned on 64 */
58 
60  {
61  fifo = Ifx_Fifo_init(fifo, size, elementSize);
62  }
63 
64  return fifo;
65 }
66 
67 
69 {
70  free(fifo);
71 }
72 
73 
74 Ifx_Fifo *Ifx_Fifo_init(void *buffer, Ifx_SizeT size, Ifx_SizeT elementSize)
75 {
76  Ifx_Fifo *fifo = NULL_PTR;
77 
78  size = Ifx_AlignOn32(size); /* data transfer is optimised for 32 bit access */
79  IFX_ASSERT(IFX_VERBOSE_LEVEL_ERROR, elementSize <= size);
80  /* Check size over maximum FIFO size */
82 
83  {
84  fifo = (Ifx_Fifo *)buffer;
85  fifo->eventReader = FALSE;
86  fifo->eventWriter = TRUE;
87  fifo->buffer = (uint8 *)Ifx_AlignOn64(((uint32)fifo) + sizeof(Ifx_Fifo));
88  fifo->shared.count = 0;
89  fifo->shared.maxcount = 0;
90  fifo->shared.readerWaitx = fifo->shared.writerWaitx = 0;
91  fifo->startIndex = fifo->endIndex = 0;
92  fifo->size = size;
93  fifo->elementSize = elementSize;
94  }
95 
96  return fifo;
97 }
98 
99 
100 /**
101  * \param count in bytes
102  */
103 static Ifx_SizeT Ifx_Fifo_beginRead(Ifx_Fifo *fifo, Ifx_SizeT count)
104 {
105  boolean interruptState;
106  Ifx_SizeT blockSize;
107 
108  interruptState = IfxCpu_disableInterrupts();
109  blockSize = __min(count, Ifx_Fifo_readCount(fifo));
110  blockSize -= blockSize % fifo->elementSize;
111  fifo->eventReader = FALSE;
112  fifo->shared.readerWaitx = __min(count - blockSize, fifo->size);
113  IfxCpu_restoreInterrupts(interruptState);
114 
115  return blockSize;
116 }
117 
118 
119 boolean Ifx_Fifo_canReadCount(Ifx_Fifo *fifo, Ifx_SizeT count, Ifx_TickTime timeout)
120 {
121  boolean result;
122 
124 
125  if (count < fifo->elementSize)
126  { /* Only complete elements can be read from the buffer */
127  result = FALSE;
128  }
129  else
130  {
131  boolean interruptState;
132  sint32 waitCount;
133  count = __min(count, fifo->size);
134  interruptState = IfxCpu_disableInterrupts();
135  waitCount = count - Ifx_Fifo_readCount(fifo);
136 
137  if (waitCount <= 0)
138  {
139  fifo->shared.readerWaitx = 0;
140  fifo->eventReader = TRUE;
141  IfxCpu_restoreInterrupts(interruptState);
142  result = TRUE;
143  }
144  else
145  {
146  Ifx_TickTime DeadLine = getDeadLine(timeout);
147  fifo->eventReader = FALSE;
148  fifo->shared.readerWaitx = waitCount;
149  IfxCpu_restoreInterrupts(interruptState);
150 
151  while ((fifo->eventReader == FALSE) && (isDeadLine(DeadLine) == FALSE))
152  {}
153 
154  result = fifo->eventReader == TRUE;
155  }
156  }
157 
158  return result;
159 }
160 
161 
162 /**
163  * \param count in bytes
164  */
165 static Ifx_SizeT Ifx_Fifo_readEnd(Ifx_Fifo *fifo, Ifx_SizeT count, Ifx_SizeT blockSize)
166 {
167  boolean interruptState;
168 
169  /* Set the shared values */
170  interruptState = IfxCpu_disableInterrupts();
171 
172  fifo->shared.count -= blockSize;
173 
174  if (fifo->shared.writerWaitx != 0)
175  {
176  fifo->shared.writerWaitx -= blockSize;
177 
178  if (fifo->shared.writerWaitx <= 0)
179  {
180  fifo->shared.writerWaitx = 0;
181  fifo->eventWriter = TRUE; /* Signal the writer */
182  }
183  }
184 
185  IfxCpu_restoreInterrupts(interruptState);
186 
187  return count - blockSize;
188 }
189 
190 
191 Ifx_SizeT Ifx_Fifo_read(Ifx_Fifo *fifo, void *data, Ifx_SizeT count, Ifx_TickTime timeout)
192 {
193  Ifx_TickTime DeadLine;
194  Ifx_SizeT blockSize;
195  Ifx_CircularBuffer buffer;
196  boolean Stop = FALSE;
197 
200 
201  if (count != 0)
202  {
203  buffer.base = fifo->buffer;
204  buffer.length = (uint16)fifo->size; /* size always fit into 16 bit */
205  buffer.index = (uint16)fifo->startIndex; /* startIndex always fit into size */
206  DeadLine = getDeadLine(timeout);
207 
208  do
209  {
210  blockSize = Ifx_Fifo_beginRead(fifo, count);
211 
212  if (blockSize != 0)
213  {
214  /* read element from the buffer */
215  data = Ifx_CircularBuffer_read8(&buffer, data, blockSize);
216  count = Ifx_Fifo_readEnd(fifo, count, blockSize);
217  }
218 
219  if ((Stop != FALSE) || (isDeadLine(DeadLine) != FALSE))
220  {
221  break;
222  }
223 
224  if (count != 0)
225  {
226  while ((fifo->eventReader == FALSE) && (isDeadLine(DeadLine) == FALSE))
227  {}
228 
229  Stop = (fifo->eventReader == FALSE); /* If the function timeout, the maximum number of characters are read before returning */
230  }
231  } while (count != 0);
232 
233  fifo->startIndex = buffer.index;
234  }
235 
236  return count;
237 }
238 
239 
241 {
242  boolean interruptState;
243 
244  interruptState = IfxCpu_disableInterrupts();
245 
246  if (fifo->shared.writerWaitx != 0)
247  {
248  fifo->shared.writerWaitx = 0;
249  fifo->eventWriter = TRUE; /* Signal the writer */
250  }
251 
252  fifo->eventReader = FALSE;
253  fifo->shared.readerWaitx = 0;
254  fifo->shared.count = 0;
255  fifo->shared.maxcount = 0;
256  fifo->startIndex = fifo->endIndex;
257  IfxCpu_restoreInterrupts(interruptState);
258 }
259 
260 
261 static Ifx_SizeT Ifx_Fifo_beginWrite(Ifx_Fifo *fifo, Ifx_SizeT count)
262 {
263  Ifx_SizeT blockSize;
264  boolean interruptState;
265 
266  interruptState = IfxCpu_disableInterrupts();
267  blockSize = __min(count, fifo->size - Ifx_Fifo_readCount(fifo));
268  blockSize -= blockSize % fifo->elementSize;
269  fifo->eventWriter = FALSE;
270  fifo->shared.writerWaitx = __min(count - blockSize, fifo->size);
271  IfxCpu_restoreInterrupts(interruptState);
272 
273  return blockSize;
274 }
275 
276 
278 {
279  boolean result;
280 
282  count = __min(count, fifo->size);
283 
284  if (count < fifo->elementSize)
285  { /* Only complete elements can be written to the buffer */
286  result = FALSE;
287  }
288  else
289  {
290  boolean interruptState;
291  interruptState = IfxCpu_disableInterrupts();
292 
293  if ((fifo->size - Ifx_Fifo_readCount(fifo)) >= count)
294  {
295  fifo->shared.writerWaitx = 0;
296  fifo->eventWriter = TRUE;
297  IfxCpu_restoreInterrupts(interruptState);
298  result = TRUE;
299  }
300  else
301  {
302  Ifx_TickTime DeadLine = getDeadLine(timeout);
303  fifo->eventWriter = FALSE;
304  fifo->shared.writerWaitx = __max(0, count - (fifo->size - Ifx_Fifo_readCount(fifo)));
305  IfxCpu_restoreInterrupts(interruptState);
306 
307  while ((fifo->eventWriter == FALSE) && (isDeadLine(DeadLine) == FALSE))
308  {}
309 
310  result = fifo->eventWriter == TRUE;
311  }
312  }
313 
314  return result;
315 }
316 
317 
318 static Ifx_SizeT Ifx_Fifo_endWrite(Ifx_Fifo *fifo, Ifx_SizeT count, Ifx_SizeT blockSize)
319 {
320  boolean interruptState;
321 
322  /* Set the shared values */
323  interruptState = IfxCpu_disableInterrupts();
324 
325  fifo->shared.count += blockSize;
326  fifo->shared.maxcount = __max(fifo->shared.maxcount, fifo->shared.count); /* Update maximum value */
327 
328  if (fifo->shared.readerWaitx != 0)
329  {
330  fifo->shared.readerWaitx -= blockSize;
331 
332  if (fifo->shared.readerWaitx <= 0)
333  {
334  fifo->shared.readerWaitx = 0;
335  fifo->eventReader = TRUE; /* Signal the reader - a re-scheduling may occur at this point! */
336  }
337  }
338 
339  IfxCpu_restoreInterrupts(interruptState);
340 
341  return count - blockSize;
342 }
343 
344 
345 Ifx_SizeT Ifx_Fifo_write(Ifx_Fifo *fifo, const void *data, Ifx_SizeT count, Ifx_TickTime timeout)
346 {
347  Ifx_TickTime DeadLine;
348  Ifx_SizeT blockSize;
349  Ifx_CircularBuffer buffer;
350  boolean Stop = FALSE;
351 
354 
355  if (count != 0)
356  {
357  buffer.base = fifo->buffer;
358  buffer.length = (uint16)fifo->size; /* size always fit into 16 bit */
359  buffer.index = (uint16)fifo->endIndex; /* startIndex always fit into size */
360  DeadLine = getDeadLine(timeout);
361 
362  do
363  {
364  blockSize = Ifx_Fifo_beginWrite(fifo, count);
365 
366  if (blockSize != 0)
367  {
368  /* write element to the buffer */
369  data = Ifx_CircularBuffer_write8(&buffer, data, blockSize);
370  count = Ifx_Fifo_endWrite(fifo, count, blockSize);
371  }
372 
373  if ((Stop != FALSE) || (isDeadLine(DeadLine) != FALSE))
374  {
375  break;
376  }
377 
378  if (count != 0)
379  {
380  while ((fifo->eventWriter == FALSE) && (isDeadLine(DeadLine) == FALSE))
381  {}
382 
383  Stop = fifo->eventWriter == FALSE; /* If the function timeout, the maximum number of characters are written before returning */
384  }
385  } while (count != 0);
386 
387  fifo->endIndex = buffer.index;
388  }
389 
390  return count;
391 }
392 
393 
394 //------------------------------------------------------------------------------