@@ -81,8 +81,8 @@ bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_si
81
81
// Limit index space to 2*depth - this allows for a fast "modulo" calculation
82
82
// but limits the maximum depth to 2^16/2 = 2^15 and buffer overflows are detectable
83
83
// only if overflow happens once (important for unsupervised DMA applications)
84
- f -> max_pointer_idx = (uint16_t ) (2 * depth - 1 );
85
- f -> non_used_index_space = UINT16_MAX - f -> max_pointer_idx ;
84
+ // f->max_pointer_idx = (uint16_t) (2*depth - 1);
85
+ f -> non_used_index_space = UINT16_MAX - ( 2 * f -> depth - 1 ) ;
86
86
87
87
f -> rd_idx = f -> wr_idx = 0 ;
88
88
@@ -320,15 +320,15 @@ static void _ff_pull_n(tu_fifo_t* f, void* app_buf, uint16_t n, uint16_t rel, tu
320
320
// Index (free-running and real buffer pointer)
321
321
//--------------------------------------------------------------------+
322
322
323
- // Advance an absolute pointer
323
+ // Advance an absolute index
324
324
// "absolute" index is only in the range of [0..2*depth)
325
- static uint16_t advance_pointer (tu_fifo_t * f , uint16_t p , uint16_t offset )
325
+ static uint16_t advance_pointer (tu_fifo_t * f , uint16_t idx , uint16_t offset )
326
326
{
327
327
// We limit the index space of p such that a correct wrap around happens
328
328
// Check for a wrap around or if we are in unused index space - This has to be checked first!!
329
329
// We are exploiting the wrap around to the correct index
330
- uint16_t next_p = (uint16_t ) (p + offset );
331
- if ( (p > next_p ) || (next_p > f -> max_pointer_idx ) )
330
+ uint16_t next_p = (uint16_t ) (idx + offset );
331
+ if ( (idx > next_p ) || (next_p >= 2 * f -> depth ) )
332
332
{
333
333
next_p = (uint16_t ) (next_p + f -> non_used_index_space );
334
334
}
@@ -343,7 +343,7 @@ static uint16_t backward_pointer(tu_fifo_t* f, uint16_t p, uint16_t offset)
343
343
// Check for a wrap around or if we are in unused index space - This has to be checked first!!
344
344
// We are exploiting the wrap around to the correct index
345
345
uint16_t new_p = (uint16_t ) (p - offset );
346
- if ( (p < new_p ) || (new_p > f -> max_pointer_idx ) )
346
+ if ( (p < new_p ) || (new_p >= 2 * f -> depth ) )
347
347
{
348
348
new_p = (uint16_t ) (new_p - f -> non_used_index_space );
349
349
}
@@ -374,15 +374,15 @@ static inline uint16_t _tu_fifo_count(tu_fifo_t* f, uint16_t wr_idx, uint16_t rd
374
374
}
375
375
376
376
// Works on local copies of w and r
377
- static inline bool _tu_fifo_empty (uint16_t wAbs , uint16_t rAbs )
377
+ static inline bool _tu_fifo_empty (uint16_t wr_idx , uint16_t rd_idx )
378
378
{
379
- return wAbs == rAbs ;
379
+ return wr_idx == rd_idx ;
380
380
}
381
381
382
382
// Works on local copies of w and r
383
383
static inline bool _tu_fifo_full (tu_fifo_t * f , uint16_t wAbs , uint16_t rAbs )
384
384
{
385
- return ( _tu_fifo_count (f , wAbs , rAbs ) == f -> depth ) ;
385
+ return _tu_fifo_count (f , wAbs , rAbs ) == f -> depth ;
386
386
}
387
387
388
388
// Works on local copies of w and r
@@ -391,9 +391,9 @@ static inline bool _tu_fifo_full(tu_fifo_t* f, uint16_t wAbs, uint16_t rAbs)
391
391
// write more than 2*depth-1 items in one rush without updating write pointer. Otherwise
392
392
// write pointer wraps and you pointer states are messed up. This can only happen if you
393
393
// use DMAs, write functions do not allow such an error.
394
- static inline bool _tu_fifo_overflowed (tu_fifo_t * f , uint16_t wAbs , uint16_t rAbs )
394
+ static inline bool _tu_fifo_overflowed (tu_fifo_t * f , uint16_t wr_idx , uint16_t rd_idx )
395
395
{
396
- return (_tu_fifo_count (f , wAbs , rAbs ) > f -> depth );
396
+ return (_tu_fifo_count (f , wr_idx , rd_idx ) > f -> depth );
397
397
}
398
398
399
399
// Works on local copies of w
@@ -466,57 +466,71 @@ static uint16_t _tu_fifo_write_n(tu_fifo_t* f, const void * data, uint16_t n, tu
466
466
{
467
467
if ( n == 0 ) return 0 ;
468
468
469
- TU_LOG (TU_FIFO_DBG , "rd = %u, wr = %02u, n = %u: " , f -> rd_idx , f -> wr_idx , n );
470
-
471
469
_ff_lock (f -> mutex_wr );
472
470
473
471
uint16_t wr_idx = f -> wr_idx ;
474
472
uint16_t rd_idx = f -> rd_idx ;
475
473
476
474
uint8_t const * buf8 = (uint8_t const * ) data ;
475
+ uint16_t overflowable_count = _tu_fifo_count (f , wr_idx , rd_idx );
477
476
uint16_t const remain = _tu_fifo_remaining (f , wr_idx , rd_idx );
478
477
479
- if ( n > remain )
478
+ TU_LOG (TU_FIFO_DBG , "rd = %3u, wr = %3u, count = %3u, remain = %3u, n = %3u: " , rd_idx , wr_idx , _tu_fifo_count (f , wr_idx , rd_idx ), remain , n );
479
+
480
+ if ( !f -> overwritable )
480
481
{
481
- if ( !f -> overwritable )
482
- {
483
- // limit up to full
484
- n = remain ;
485
- }
486
- else
482
+ // limit up to full
483
+ n = tu_min16 (n , remain );
484
+ }
485
+ else
486
+ {
487
+ // In over-writable mode, fifo_write() is allowed even when fifo is full. In such case,
488
+ // oldest data in fifo i.e at read pointer data will be overwritten
489
+ // Note: we can modify read buffer contents but we must not modify the read index itself within a write function!
490
+ // Since it would end up in a race condition with read functions!
491
+ if ( n >= f -> depth )
487
492
{
488
- // oldest data in fifo i.e read pointer data will be overwritten
489
- // Note: we modify read data but we do not want to modify the read pointer within a write function!
490
- // since it would end up in a race condition with read functions!
491
- // Note2: race condition could still occur if tu_fifo_read() is called while we modify its buffer (corrupted data)
492
-
493
- if ( n >= f -> depth )
493
+ // Only copy last part
494
+ if ( copy_mode == TU_FIFO_COPY_INC )
494
495
{
495
- // Only copy last part
496
- buf8 = buf8 + (n - f -> depth ) * f -> item_size ;
497
- n = f -> depth ;
498
-
499
- // We start writing at the read pointer's position since we fill the complete
500
- // buffer and we do not want to modify the read pointer within a write function!
501
- // This would end up in a race condition with read functions!
502
- wr_idx = rd_idx ;
496
+ buf8 += (n - f -> depth ) * f -> item_size ;
503
497
}else
504
498
{
505
- // TODO shift out oldest data from read pointer !!!
499
+ // TODO should read from hw fifo to discard data, however reading an odd number could
500
+ // accidentally discard data.
506
501
}
502
+
503
+ n = f -> depth ;
504
+
505
+ // We start writing at the read pointer's position since we fill the whole buffer
506
+ wr_idx = rd_idx ;
507
+ }else if (overflowable_count + n >= 2 * f -> depth )
508
+ {
509
+ // Double overflowed
510
+ // re-position write index to have a full fifo after pushed
511
+ wr_idx = advance_pointer (f , rd_idx , f -> depth - n );
512
+
513
+ // TODO we should also shift out n bytes from read index since we avoid changing rd index !!
514
+ // However memmove() is expensive due to actual copying + wrapping consideration.
515
+ // Also race condition could happen anyway if read() is invoke while moving result in corrupted memory
516
+ // currently deliberately not implemented --> result in incorrect data read back
517
+ }else
518
+ {
519
+ // normal + single overflowed: just increase write index
520
+ // we will correct (re-position) read index later on in fifo_read() function
507
521
}
508
522
}
509
523
510
524
if (n )
511
525
{
512
526
uint16_t wr_ptr = idx2ptr (wr_idx , f -> depth );
513
527
514
- TU_LOG (TU_FIFO_DBG , "actual_n = %u, wr_rel = %u" , n , wr_ptr );
528
+ TU_LOG (TU_FIFO_DBG , "actual_n = %u, wr_ptr = %u" , n , wr_ptr );
515
529
516
530
// Write data
517
531
_ff_push_n (f , buf8 , n , wr_ptr , copy_mode );
518
532
519
- // Advance pointer
533
+ // Advance index
520
534
f -> wr_idx = advance_pointer (f , wr_idx , n );
521
535
522
536
TU_LOG (TU_FIFO_DBG , "\tnew_wr = %u\n" , f -> wr_idx );
@@ -850,8 +864,8 @@ bool tu_fifo_clear(tu_fifo_t *f)
850
864
_ff_lock (f -> mutex_rd );
851
865
852
866
f -> rd_idx = f -> wr_idx = 0 ;
853
- f -> max_pointer_idx = (uint16_t ) (2 * f -> depth - 1 );
854
- f -> non_used_index_space = UINT16_MAX - f -> max_pointer_idx ;
867
+ // f->max_pointer_idx = (uint16_t) (2*f->depth-1);
868
+ f -> non_used_index_space = UINT16_MAX - ( 2 * f -> depth - 1 ) ;
855
869
856
870
_ff_unlock (f -> mutex_wr );
857
871
_ff_unlock (f -> mutex_rd );
0 commit comments