espressif_tinyusb/src/common/tusb_fifo.c

644 lines
20 KiB
C
Raw Normal View History

2020-01-15 05:30:39 +01:00
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
2020-09-19 11:46:43 +02:00
* Copyright (c) 2020 Reinhard Panhuber - rework to unmasked pointers
2020-01-15 05:30:39 +01:00
*
* 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.
*
* This file is part of the TinyUSB stack.
*/
#include <string.h>
#include "osal/osal.h"
#include "tusb_fifo.h"
// implement mutex lock and unlock
#if CFG_FIFO_MUTEX
static void tu_fifo_lock(tu_fifo_t *f)
{
if (f->mutex)
{
osal_mutex_lock(f->mutex, OSAL_TIMEOUT_WAIT_FOREVER);
}
}
static void tu_fifo_unlock(tu_fifo_t *f)
{
if (f->mutex)
{
osal_mutex_unlock(f->mutex);
}
}
#else
#define tu_fifo_lock(_ff)
#define tu_fifo_unlock(_ff)
#endif
bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable)
{
tu_fifo_lock(f);
f->buffer = (uint8_t*) buffer;
f->depth = depth;
f->item_size = item_size;
f->overwritable = overwritable;
2020-09-15 20:40:41 +02:00
f->non_used_index_space = 0x10000 % depth;
f->max_pointer_idx = 0xFFFF - f->non_used_index_space;
2020-09-14 18:24:08 +02:00
f->rd_idx = f->wr_idx = 0;
2020-01-15 05:30:39 +01:00
tu_fifo_unlock(f);
return true;
}
2020-09-19 11:46:43 +02:00
// Static functions are intended to work on local variables
2020-05-14 09:24:55 +02:00
static inline uint16_t _ff_mod(uint16_t idx, uint16_t depth)
{
2020-09-15 20:40:41 +02:00
return idx % depth;
2020-05-14 09:24:55 +02:00
}
2020-09-14 18:24:08 +02:00
// send one item to FIFO WITHOUT updating write pointer
2020-09-15 20:40:41 +02:00
static inline void _ff_push(tu_fifo_t* f, void const * data, uint16_t wRel)
2020-09-14 18:24:08 +02:00
{
2020-09-15 20:40:41 +02:00
memcpy(f->buffer + (wRel * f->item_size), data, f->item_size);
2020-09-14 18:24:08 +02:00
}
// send n items to FIFO WITHOUT updating write pointer
static void _ff_push_n(tu_fifo_t* f, void const * data, uint16_t n, uint16_t wRel)
2020-01-15 05:30:39 +01:00
{
2020-09-14 18:24:08 +02:00
if(wRel + n <= f->depth) // Linear mode only
{
memcpy(f->buffer + (wRel * f->item_size), data, n*f->item_size);
}
else // Wrap around
{
uint16_t nLin = f->depth - wRel;
// Write data to linear part of buffer
memcpy(f->buffer + (wRel * f->item_size), data, nLin*f->item_size);
// Write data wrapped around
memcpy(f->buffer, data + nLin*f->item_size, (n - nLin) * f->item_size);
}
}
2020-01-15 05:30:39 +01:00
2020-09-14 18:24:08 +02:00
// get one item from FIFO WITHOUT updating write pointer
2020-09-15 20:40:41 +02:00
static inline void _ff_pull(tu_fifo_t* f, void * p_buffer, uint16_t rRel)
2020-09-14 18:24:08 +02:00
{
memcpy(p_buffer, f->buffer + (rRel * f->item_size), f->item_size);
2020-01-15 05:30:39 +01:00
}
2020-09-14 18:24:08 +02:00
// get n items from FIFO WITHOUT updating write pointer
2020-09-15 20:40:41 +02:00
static void _ff_pull_n(tu_fifo_t* f, void * p_buffer, uint16_t n, uint16_t rRel)
2020-01-15 05:30:39 +01:00
{
2020-09-14 18:24:08 +02:00
if(rRel + n <= f->depth) // Linear mode only
{
memcpy(p_buffer, f->buffer + (rRel * f->item_size), n*f->item_size);
}
else // Wrap around
{
uint16_t nLin = f->depth - rRel;
2020-01-15 05:30:39 +01:00
2020-09-14 18:24:08 +02:00
// Read data from linear part of buffer
memcpy(p_buffer, f->buffer + (rRel * f->item_size), nLin*f->item_size);
2020-01-15 05:30:39 +01:00
2020-09-14 18:24:08 +02:00
// Read data wrapped part
memcpy(p_buffer + nLin*f->item_size, f->buffer, (n - nLin) * f->item_size);
}
}
// Advance an absolute pointer
static uint16_t advance_pointer(tu_fifo_t* f, uint16_t p, uint16_t pos)
{
// We limit the index space of p such that a correct wrap around happens
// Check for a wrap around or if we are in unused index space - This has to be checked first!! We are exploiting the wrap around to the correct index
2020-09-15 20:40:41 +02:00
if ((p > p + pos) || (p + pos > f->max_pointer_idx))
2020-01-15 05:30:39 +01:00
{
2020-09-14 18:24:08 +02:00
p = (p + pos) + f->non_used_index_space;
2020-01-15 05:30:39 +01:00
}
else
{
2020-09-14 18:24:08 +02:00
p += pos;
}
return p;
}
2020-09-19 11:46:43 +02:00
// Backward an absolute pointer
static uint16_t backward_pointer(tu_fifo_t* f, uint16_t p, uint16_t pos)
{
// We limit the index space of p such that a correct wrap around happens
// Check for a wrap around or if we are in unused index space - This has to be checked first!! We are exploiting the wrap around to the correct index
if ((p < p - pos) || (p - pos > f->max_pointer_idx))
{
p = (p - pos) - f->non_used_index_space;
}
else
{
p -= pos;
}
return p;
}
2020-09-14 18:24:08 +02:00
// get relative from absolute pointer
static uint16_t get_relative_pointer(tu_fifo_t* f, uint16_t p, uint16_t pos)
{
return _ff_mod(advance_pointer(f, p, pos), f->depth);
}
// Works on local copies of w and r
static uint16_t _tu_fifo_count(tu_fifo_t* f, uint16_t wAbs, uint16_t rAbs)
{
uint16_t cnt = wAbs-rAbs;
// In case we have non-power of two depth we need a further modification
if (rAbs > wAbs) cnt -= f->non_used_index_space;
return cnt;
}
// Works on local copies of w and r
static inline bool _tu_fifo_empty(uint16_t wAbs, uint16_t rAbs)
{
return wAbs == rAbs;
}
// Works on local copies of w and r
static inline bool _tu_fifo_full(tu_fifo_t* f, uint16_t wAbs, uint16_t rAbs)
{
return (_tu_fifo_count(f, wAbs, rAbs) == f->depth);
}
// Works on local copies of w and r
2020-09-19 11:46:43 +02:00
//BE AWARE - THIS FUNCTION MIGHT NOT GIVE A CORRECT ANSWERE IN CASE WRITE POINTER "OVERFLOWS"
//EXAMPLE with buffer depth: 100
//Maximum index space: (2^16) - (2^16) % depth = 65500
//If you produce 65500 / 100 + 1 = 656 buffer overflows, the write pointer will overflow as well and
//the check _tu_fifo_overflow() will not give you a valid result! Avoid such nasty things!
//All reading functions (read, peek) check for overflows and correct read pointer on their own such
//that latest items are read.
//If required (e.g. for DMA use) you can also correct the read pointer by
//tu_fifo_correct_read_pointer().
2020-09-14 18:24:08 +02:00
static inline bool _tu_fifo_overflow(tu_fifo_t* f, uint16_t wAbs, uint16_t rAbs)
{
return (_tu_fifo_count(f, wAbs, rAbs) > f->depth);
}
// Works on local copies of w
// For more details see _tu_fifo_overflow()!
static inline void _tu_fifo_correct_read_pointer(tu_fifo_t* f, uint16_t wAbs)
{
2020-09-19 11:46:43 +02:00
f->rd_idx = backward_pointer(f, wAbs, f->depth);
2020-09-14 18:24:08 +02:00
}
// Works on local copies of w and r
2020-09-19 11:46:43 +02:00
// Must be protected by mutexes since in case of an overflow read pointer gets modified
2020-09-14 18:24:08 +02:00
static bool _tu_fifo_peek_at(tu_fifo_t* f, uint16_t pos, void * p_buffer, uint16_t wAbs, uint16_t rAbs)
{
uint16_t cnt = _tu_fifo_count(f, wAbs, rAbs);
2020-09-19 11:46:43 +02:00
// Check overflow and correct if required
if (cnt > f->depth)
{
_tu_fifo_correct_read_pointer(f, wAbs);
cnt = f->depth;
}
2020-09-14 18:24:08 +02:00
// Skip beginning of buffer
if (cnt == 0 || pos >= cnt) return false;
uint16_t rRel = get_relative_pointer(f, rAbs, pos);
// Peek data
_ff_pull(f, p_buffer, rRel);
return true;
}
// Works on local copies of w and r
2020-09-19 11:46:43 +02:00
// Must be protected by mutexes since in case of an overflow read pointer gets modified
2020-09-14 18:24:08 +02:00
static uint16_t _tu_fifo_peek_at_n(tu_fifo_t* f, uint16_t pos, void * p_buffer, uint16_t n, uint16_t wAbs, uint16_t rAbs)
{
uint16_t cnt = _tu_fifo_count(f, wAbs, rAbs);
2020-09-19 11:46:43 +02:00
// Check overflow and correct if required
if (cnt > f->depth)
{
_tu_fifo_correct_read_pointer(f, wAbs);
cnt = f->depth;
}
2020-09-14 18:24:08 +02:00
// Skip beginning of buffer
if (cnt == 0 || pos >= cnt) return 0;
// Check if we can read something at and after pos - if too less is available we read what remains
cnt -= pos;
if (cnt < n) {
if (cnt == 0) return 0;
n = cnt;
2020-01-15 05:30:39 +01:00
}
2020-09-14 18:24:08 +02:00
uint16_t rRel = get_relative_pointer(f, rAbs, pos);
// Peek data
_ff_pull_n(f, p_buffer, n, rRel);
return n;
}
// Works on local copies of w and r
static inline uint16_t _tu_fifo_remaining(tu_fifo_t* f, uint16_t wAbs, uint16_t rAbs)
{
return f->depth - _tu_fifo_count(f, wAbs, rAbs);
2020-01-15 05:30:39 +01:00
}
/******************************************************************************/
/*!
2020-09-14 18:24:08 +02:00
@brief Get number of items in FIFO.
As this function only reads the read and write pointers once, this function is
reentrant and thus thread and ISR save without any mutexes.
@param[in] f
Pointer to the FIFO buffer to manipulate
@returns Number of items in FIFO
*/
/******************************************************************************/
uint16_t tu_fifo_count(tu_fifo_t* f)
{
return _tu_fifo_count(f, f->wr_idx, f->rd_idx);
}
/******************************************************************************/
/*!
@brief Check if FIFO is empty.
As this function only reads the read and write pointers once, this function is
reentrant and thus thread and ISR save without any mutexes.
@param[in] f
Pointer to the FIFO buffer to manipulate
@returns Number of items in FIFO
*/
/******************************************************************************/
bool tu_fifo_empty(tu_fifo_t* f)
{
return _tu_fifo_empty(f->wr_idx, f->rd_idx);
}
/******************************************************************************/
/*!
@brief Check if FIFO is full.
As this function only reads the read and write pointers once, this function is
reentrant and thus thread and ISR save without any mutexes.
@param[in] f
Pointer to the FIFO buffer to manipulate
@returns Number of items in FIFO
*/
/******************************************************************************/
bool tu_fifo_full(tu_fifo_t* f)
{
return _tu_fifo_full(f, f->wr_idx, f->rd_idx);
}
/******************************************************************************/
/*!
@brief Get remaining space in FIFO.
As this function only reads the read and write pointers once, this function is
reentrant and thus thread and ISR save without any mutexes.
@param[in] f
Pointer to the FIFO buffer to manipulate
@returns Number of items in FIFO
*/
/******************************************************************************/
uint16_t tu_fifo_remaining(tu_fifo_t* f)
{
return _tu_fifo_remaining(f, f->wr_idx, f->rd_idx);
}
/******************************************************************************/
/*!
@brief Check if overflow happened.
BE AWARE - THIS FUNCTION MIGHT NOT GIVE A CORRECT ANSWERE IN CASE WRITE POINTER "OVERFLOWS"
EXAMPLE with buffer depth: 100
2020-09-19 11:46:43 +02:00
Maximum index space: (2^16) - (2^16) % depth = 65500
If you produce 65500 / 100 + 1 = 656 buffer overflows, the write pointer will overflow as well and
2020-09-14 18:24:08 +02:00
the check _tu_fifo_overflow() will not give you a valid result! Avoid such nasty things!
2020-09-19 11:46:43 +02:00
All reading functions (read, peek) check for overflows and correct read pointer on their own such
that latest items are read.
If required (e.g. for DMA use) you can also correct the read pointer by
tu_fifo_correct_read_pointer().
2020-09-14 18:24:08 +02:00
@param[in] f
Pointer to the FIFO buffer to manipulate
@returns True if overflow happened
*/
/******************************************************************************/
bool tu_fifo_overflow(tu_fifo_t* f)
{
return _tu_fifo_overflow(f, f->wr_idx, f->rd_idx);
}
// Only use in case tu_fifo_overflow() returned true!
void tu_fifo_correct_read_pointer(tu_fifo_t* f)
{
2020-09-19 11:46:43 +02:00
tu_fifo_lock(f);
2020-09-14 18:24:08 +02:00
_tu_fifo_correct_read_pointer(f, f->wr_idx);
2020-09-19 11:46:43 +02:00
tu_fifo_unlock(f);
2020-09-14 18:24:08 +02:00
}
/******************************************************************************/
/*!
@brief Read one element out of the buffer.
2020-01-15 05:30:39 +01:00
This function will return the element located at the array index of the
2020-09-19 11:46:43 +02:00
read pointer, and then increment the read pointer index.
This function checks for an overflow and corrects read pointer if required.
2020-01-15 05:30:39 +01:00
@param[in] f
Pointer to the FIFO buffer to manipulate
@param[in] buffer
Pointer to the place holder for data read from the buffer
@returns TRUE if the queue is not empty
2020-09-14 18:24:08 +02:00
*/
2020-01-15 05:30:39 +01:00
/******************************************************************************/
bool tu_fifo_read(tu_fifo_t* f, void * buffer)
{
2020-09-14 18:24:08 +02:00
tu_fifo_lock(f); // TODO: Here we may distinguish for read and write pointer mutexes!
2020-01-15 05:30:39 +01:00
2020-09-14 18:24:08 +02:00
uint16_t r = f->rd_idx;
2020-01-15 05:30:39 +01:00
2020-09-14 18:24:08 +02:00
// Peek the data
bool ret = _tu_fifo_peek_at(f, 0, buffer, f->wr_idx, r);
2020-01-15 05:30:39 +01:00
2020-09-14 18:24:08 +02:00
// Advance pointer
f->rd_idx = advance_pointer(f, r, ret);
2020-01-15 05:30:39 +01:00
2020-09-14 18:24:08 +02:00
tu_fifo_unlock(f);
return ret;
2020-01-15 05:30:39 +01:00
}
/******************************************************************************/
/*!
@brief This function will read n elements from the array index specified by
2020-09-19 11:46:43 +02:00
the read pointer and increment the read index.
This function checks for an overflow and corrects read pointer if required.
2020-01-15 05:30:39 +01:00
@param[in] f
Pointer to the FIFO buffer to manipulate
@param[in] buffer
The pointer to data location
@param[in] count
Number of element that buffer can afford
@returns number of items read from the FIFO
2020-09-14 18:24:08 +02:00
*/
2020-01-15 05:30:39 +01:00
/******************************************************************************/
2020-09-14 18:24:08 +02:00
uint16_t tu_fifo_read_n(tu_fifo_t* f, void * buffer, uint16_t count)
2020-01-15 05:30:39 +01:00
{
2020-09-14 18:24:08 +02:00
tu_fifo_lock(f); // TODO: Here we may distinguish for read and write pointer mutexes!
2020-01-15 05:30:39 +01:00
2020-09-14 18:24:08 +02:00
uint16_t r = f->rd_idx;
2020-01-15 05:30:39 +01:00
2020-09-14 18:24:08 +02:00
// Peek the data
count = _tu_fifo_peek_at_n(f, 0, buffer, count, f->wr_idx, r);
2020-01-15 05:30:39 +01:00
2020-09-14 18:24:08 +02:00
// Advance read pointer
f->rd_idx = advance_pointer(f, r, count);
2020-01-15 05:30:39 +01:00
tu_fifo_unlock(f);
return count;
2020-01-15 05:30:39 +01:00
}
/******************************************************************************/
/*!
2020-09-19 11:46:43 +02:00
@brief Read one item without removing it from the FIFO.
This function checks for an overflow and corrects read pointer if required.
2020-01-15 05:30:39 +01:00
@param[in] f
Pointer to the FIFO buffer to manipulate
@param[in] pos
2020-09-19 11:46:43 +02:00
Position to read from in the FIFO buffer with respect to read pointer
2020-01-15 05:30:39 +01:00
@param[in] p_buffer
Pointer to the place holder for data read from the buffer
@returns TRUE if the queue is not empty
2020-09-14 18:24:08 +02:00
*/
2020-01-15 05:30:39 +01:00
/******************************************************************************/
bool tu_fifo_peek_at(tu_fifo_t* f, uint16_t pos, void * p_buffer)
{
2020-09-19 11:46:43 +02:00
tu_fifo_lock(f); // TODO: Here we may distinguish for read and write pointer mutexes!
bool ret = _tu_fifo_peek_at(f, pos, p_buffer, f->wr_idx, f->rd_idx);
tu_fifo_unlock(f);
return ret;
2020-09-14 18:24:08 +02:00
}
2020-05-14 09:24:55 +02:00
2020-09-14 18:24:08 +02:00
/******************************************************************************/
/*!
@brief Read n items without removing it from the FIFO
2020-09-19 11:46:43 +02:00
This function checks for an overflow and corrects read pointer if required.
2020-01-15 05:30:39 +01:00
2020-09-14 18:24:08 +02:00
@param[in] f
Pointer to the FIFO buffer to manipulate
@param[in] pos
2020-09-19 11:46:43 +02:00
Position to read from in the FIFO buffer with respect to read pointer
2020-09-14 18:24:08 +02:00
@param[in] p_buffer
Pointer to the place holder for data read from the buffer
@param[in] n
Number of items to peek
2020-05-14 09:24:55 +02:00
2020-09-14 18:24:08 +02:00
@returns Number of bytes written to p_buffer
*/
/******************************************************************************/
uint16_t tu_fifo_peek_at_n(tu_fifo_t* f, uint16_t pos, void * p_buffer, uint16_t n)
{
2020-09-19 11:46:43 +02:00
tu_fifo_lock(f); // TODO: Here we may distinguish for read and write pointer mutexes!
bool ret = _tu_fifo_peek_at_n(f, pos, p_buffer, n, f->wr_idx, f->rd_idx);
tu_fifo_unlock(f);
return ret;
2020-01-15 05:30:39 +01:00
}
/******************************************************************************/
/*!
2020-09-14 18:24:08 +02:00
@brief Write one element into the buffer.
2020-01-15 05:30:39 +01:00
This function will write one element into the array index specified by
2020-09-19 11:46:43 +02:00
the write pointer and increment the write index.
2020-01-15 05:30:39 +01:00
@param[in] f
Pointer to the FIFO buffer to manipulate
@param[in] data
The byte to add to the FIFO
@returns TRUE if the data was written to the FIFO (overwrittable
FIFO will always return TRUE)
2020-09-14 18:24:08 +02:00
*/
2020-01-15 05:30:39 +01:00
/******************************************************************************/
2020-09-14 18:24:08 +02:00
bool tu_fifo_write(tu_fifo_t* f, const void * data)
2020-01-15 05:30:39 +01:00
{
tu_fifo_lock(f);
2020-09-14 18:24:08 +02:00
uint16_t w = f->wr_idx;
if ( _tu_fifo_full(f, w, f->rd_idx) && !f->overwritable ) return false;
uint16_t wRel = get_relative_pointer(f, w, 0);
// Write data
_ff_push(f, data, wRel);
// Advance pointer
f->wr_idx = advance_pointer(f, w, 1);
2020-01-15 05:30:39 +01:00
tu_fifo_unlock(f);
return true;
}
/******************************************************************************/
/*!
@brief This function will write n elements into the array index specified by
2020-09-19 11:46:43 +02:00
the write pointer and increment the write index.
2020-01-15 05:30:39 +01:00
@param[in] f
Pointer to the FIFO buffer to manipulate
@param[in] data
The pointer to data to add to the FIFO
@param[in] count
Number of element
@return Number of written elements
2020-09-14 18:24:08 +02:00
*/
2020-01-15 05:30:39 +01:00
/******************************************************************************/
2020-09-14 18:24:08 +02:00
uint16_t tu_fifo_write_n(tu_fifo_t* f, const void * data, uint16_t count)
2020-01-15 05:30:39 +01:00
{
if ( count == 0 ) return 0;
tu_fifo_lock(f);
2020-09-14 18:24:08 +02:00
uint16_t w = f->wr_idx, r = f->rd_idx;
2020-01-15 05:30:39 +01:00
uint8_t const* buf8 = (uint8_t const*) data;
2020-05-14 09:24:55 +02:00
if (!f->overwritable)
2020-01-15 05:30:39 +01:00
{
2020-05-14 09:24:55 +02:00
// Not overwritable limit up to full
2020-09-14 18:24:08 +02:00
count = tu_min16(count, _tu_fifo_remaining(f, w, r));
}
else if (count > f->depth)
{
2020-05-14 09:24:55 +02:00
// Only copy last part
buf8 = buf8 + (count - f->depth) * f->item_size;
count = f->depth;
2020-01-15 05:30:39 +01:00
2020-09-14 18:24:08 +02:00
// We start writing at the read pointer's position since we fill the complete
// buffer and we do not want to modify the read pointer within a write function!
// This would end up in a race condition with read functions!
f->wr_idx = r;
}
2020-05-14 09:24:55 +02:00
2020-09-14 18:24:08 +02:00
uint16_t wRel = get_relative_pointer(f, w, 0);
// Write data
_ff_push_n(f, buf8, count, wRel);
// Advance pointer
f->wr_idx = advance_pointer(f, w, count);
2020-05-14 09:24:55 +02:00
2020-01-15 05:30:39 +01:00
tu_fifo_unlock(f);
return count;
2020-01-15 05:30:39 +01:00
}
/******************************************************************************/
/*!
2020-09-19 11:46:43 +02:00
@brief Clear the fifo read and write pointers
2020-01-15 05:30:39 +01:00
@param[in] f
Pointer to the FIFO buffer to manipulate
2020-09-14 18:24:08 +02:00
*/
2020-01-15 05:30:39 +01:00
/******************************************************************************/
bool tu_fifo_clear(tu_fifo_t *f)
{
tu_fifo_lock(f);
2020-09-14 18:24:08 +02:00
f->rd_idx = f->wr_idx = 0;
2020-01-15 05:30:39 +01:00
tu_fifo_unlock(f);
return true;
}
2020-09-19 11:46:43 +02:00
/******************************************************************************/
/*!
@brief Advance write pointer - intended to be used in combination with DMA.
It is possible to fill the FIFO by use of a DMA in circular mode. Within
DMA ISRs you may update the write pointer to be able to read from the FIFO.
As long as the DMA is the only process writing into the FIFO this is safe
to use.
USE WITH CARE - WE DO NOT CONDUCT SAFTY CHECKS HERE!
@param[in] f
Pointer to the FIFO buffer to manipulate
@param[in] n
Number of items the write pointer moves forward
*/
/******************************************************************************/
void tu_fifo_advance_write_pointer(tu_fifo_t *f, uint16_t n)
{
f->wr_idx = advance_pointer(f, f->wr_idx, n);
}
/******************************************************************************/
/*!
@brief Advance read pointer - intended to be used in combination with DMA.
It is possible to read from the FIFO by use of a DMA in linear mode. Within
DMA ISRs you may update the read pointer to be able to again write into the
FIFO. As long as the DMA is the only process reading from the FIFO this is
safe to use.
USE WITH CARE - WE DO NOT CONDUCT SAFTY CHECKS HERE!
@param[in] f
Pointer to the FIFO buffer to manipulate
@param[in] n
Number of items the read pointer moves forward
*/
/******************************************************************************/
void tu_fifo_advance_read_pointer(tu_fifo_t *f, uint16_t n)
{
f->rd_idx = advance_pointer(f, f->rd_idx, n);
}