summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorhathach <[email protected]>2025-11-21 14:51:54 +0700
committerhathach <[email protected]>2025-11-21 14:51:54 +0700
commitd0d56a51a15dbdb760f5607702cf4ceeb2451a9e (patch)
tree334e42bf49f42fa40fe52785a43db05f1ebb6b59 /src
parentd4cdc096caa9c662f77f5633a792335f74fdad97 (diff)
more tu_fifo refactor
Diffstat (limited to 'src')
-rw-r--r--src/common/tusb_fifo.c145
-rw-r--r--src/common/tusb_fifo.h74
2 files changed, 81 insertions, 138 deletions
diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c
index ef2344801..c83f323e6 100644
--- a/src/common/tusb_fifo.c
+++ b/src/common/tusb_fifo.c
@@ -70,10 +70,10 @@ bool tu_fifo_config(tu_fifo_t *f, void *buffer, uint16_t depth, uint16_t item_si
f->buffer = (uint8_t *)buffer;
f->depth = depth;
- f->item_size = (uint16_t)(item_size & 0x7FFF);
+ f->item_size = (uint16_t)(item_size & 0x7FFFu);
f->overwritable = overwritable;
- f->rd_idx = 0;
- f->wr_idx = 0;
+ f->rd_idx = 0u;
+ f->wr_idx = 0u;
_ff_unlock(f->mutex_wr);
_ff_unlock(f->mutex_rd);
@@ -85,7 +85,7 @@ bool tu_fifo_config(tu_fifo_t *f, void *buffer, uint16_t depth, uint16_t item_si
// Pull & Push
//--------------------------------------------------------------------+
-#ifdef CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_RW32
+#ifdef CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_RW32
// Intended to be used to read from hardware USB FIFO in e.g. STM32 where all data is read from a constant address
// Code adapted from dcd_synopsys.c
// TODO generalize with configurable 1 byte or 4 byte each read
@@ -298,26 +298,6 @@ static void _ff_pull_n(tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd_ptr,
}
//--------------------------------------------------------------------+
-// Helper
-//--------------------------------------------------------------------+
-
-// return only the index difference and as such can be used to determine an overflow i.e overflowable count
-TU_ATTR_ALWAYS_INLINE static inline uint16_t _ff_count(uint16_t depth, uint16_t wr_idx, uint16_t rd_idx) {
- // In case we have non-power of two depth we need a further modification
- if (wr_idx >= rd_idx) {
- return (uint16_t)(wr_idx - rd_idx);
- } else {
- return (uint16_t)(2 * depth - (rd_idx - wr_idx));
- }
-}
-
-// return remaining slot in fifo
-TU_ATTR_ALWAYS_INLINE static inline uint16_t _ff_remaining(uint16_t depth, uint16_t wr_idx, uint16_t rd_idx) {
- const uint16_t count = _ff_count(depth, wr_idx, rd_idx);
- return (depth > count) ? (depth - count) : 0;
-}
-
-//--------------------------------------------------------------------+
// Index Helper
//--------------------------------------------------------------------+
@@ -346,9 +326,9 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t idx2ptr(uint16_t depth, uint16_t id
}
// Works on local copies of w
-// When an overwritable fifo is overflowed, rd_idx will be re-index so that it forms
-// an full fifo i.e _ff_count() = depth
-TU_ATTR_ALWAYS_INLINE static inline uint16_t _ff_correct_read_index(tu_fifo_t *f, uint16_t wr_idx) {
+// When an overwritable fifo is overflowed, rd_idx will be re-index so that it forms a full fifo i.e
+// tu_ff_overflow_count() = depth
+TU_ATTR_ALWAYS_INLINE static inline uint16_t ff_correct_read_index(tu_fifo_t *f, uint16_t wr_idx) {
uint16_t rd_idx;
if (wr_idx >= f->depth) {
rd_idx = wr_idx - f->depth;
@@ -364,7 +344,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t _ff_correct_read_index(tu_fifo_t *f
// Works on local copies of w and r
// Must be protected by mutexes since in case of an overflow read pointer gets modified
static bool _tu_fifo_peek(tu_fifo_t *f, void *p_buffer, uint16_t wr_idx, uint16_t rd_idx) {
- uint16_t cnt = _ff_count(f->depth, wr_idx, rd_idx);
+ uint16_t cnt = tu_ff_overflow_count(f->depth, wr_idx, rd_idx);
// nothing to peek
if (cnt == 0) {
@@ -373,7 +353,7 @@ static bool _tu_fifo_peek(tu_fifo_t *f, void *p_buffer, uint16_t wr_idx, uint16_
// Check overflow and correct if required
if (cnt > f->depth) {
- rd_idx = _ff_correct_read_index(f, wr_idx);
+ rd_idx = ff_correct_read_index(f, wr_idx);
}
uint16_t rd_ptr = idx2ptr(f->depth, rd_idx);
@@ -384,11 +364,15 @@ static bool _tu_fifo_peek(tu_fifo_t *f, void *p_buffer, uint16_t wr_idx, uint16_
return true;
}
+//--------------------------------------------------------------------+
+// Application API
+//--------------------------------------------------------------------+
+
// Works on local copies of w and r
// Must be protected by mutexes since in case of an overflow read pointer gets modified
uint16_t tu_fifo_peek_n_access(tu_fifo_t *f, void *p_buffer, uint16_t n, uint16_t wr_idx, uint16_t rd_idx,
tu_fifo_access_mode_t access_mode) {
- uint16_t cnt = _ff_count(f->depth, wr_idx, rd_idx);
+ uint16_t cnt = tu_ff_overflow_count(f->depth, wr_idx, rd_idx);
if (cnt == 0) {
return 0; // nothing to peek
@@ -396,7 +380,7 @@ uint16_t tu_fifo_peek_n_access(tu_fifo_t *f, void *p_buffer, uint16_t n, uint16_
// Check overflow and correct if required
if (cnt > f->depth) {
- rd_idx = _ff_correct_read_index(f, wr_idx);
+ rd_idx = ff_correct_read_index(f, wr_idx);
cnt = f->depth;
}
@@ -422,13 +406,12 @@ uint16_t tu_fifo_write_n_access(tu_fifo_t *f, const void *data, uint16_t n, tu_f
const uint8_t *buf8 = (const uint8_t *)data;
- TU_LOG(
- TU_FIFO_DBG, "rd = %3u, wr = %3u, count = %3u, remain = %3u, n = %3u: ", rd_idx, wr_idx,
- _ff_count(f->depth, wr_idx, rd_idx), _ff_remaining(f->depth, wr_idx, rd_idx), n);
+ TU_LOG(TU_FIFO_DBG, "rd = %3u, wr = %3u, count = %3u, remain = %3u, n = %3u: ", rd_idx, wr_idx,
+ _ff_count(f->depth, wr_idx, rd_idx), _ff_remaining(f->depth, wr_idx, rd_idx), n);
if (!f->overwritable) {
// limit up to full
- const uint16_t remain = _ff_remaining(f->depth, wr_idx, rd_idx);
+ const uint16_t remain = tu_ff_remaining_local(f->depth, wr_idx, rd_idx);
n = tu_min16(n, remain);
} else {
// In over-writable mode, fifo_write() is allowed even when fifo is full. In such case,
@@ -449,7 +432,7 @@ uint16_t tu_fifo_write_n_access(tu_fifo_t *f, const void *data, uint16_t n, tu_f
// We start writing at the read pointer's position since we fill the whole buffer
wr_idx = rd_idx;
} else {
- const uint16_t overflowable_count = _ff_count(f->depth, wr_idx, rd_idx);
+ const uint16_t overflowable_count = tu_ff_overflow_count(f->depth, wr_idx, rd_idx);
if (overflowable_count + n >= 2 * f->depth) {
// Double overflowed
// Index is bigger than the allowed range [0,2*depth)
@@ -498,92 +481,10 @@ uint16_t tu_fifo_read_n_access(tu_fifo_t *f, void *buffer, uint16_t n, tu_fifo_a
return n;
}
-//--------------------------------------------------------------------+
-// Application API
-//--------------------------------------------------------------------+
-
-/******************************************************************************/
-/*!
- @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. In case an
- overflow occurred, this function return f.depth at maximum. Overflows are
- checked and corrected for in the read functions!
-
- @param[in] f
- Pointer to the FIFO buffer to manipulate
-
- @returns Number of items in FIFO
- */
-/******************************************************************************/
-uint16_t tu_fifo_count(const tu_fifo_t *f) {
- return tu_min16(_ff_count(f->depth, f->wr_idx, f->rd_idx), f->depth);
-}
-
-/******************************************************************************/
-/*!
- @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(const tu_fifo_t *f) {
- return _ff_count(f->depth, f->wr_idx, f->rd_idx) >= f->depth;
-}
-
-/******************************************************************************/
-/*!
- @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(const tu_fifo_t *f) {
- return _ff_remaining(f->depth, 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"
- Only one overflow is allowed for this function to work e.g. if depth = 100, you must not
- write more than 2*depth-1 items in one rush without updating write pointer. Otherwise
- write pointer wraps and your pointer states are messed up. This can only happen if you
- use DMAs, write functions do not allow such an error. 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().
-
- @param[in] f
- Pointer to the FIFO buffer to manipulate
-
- @returns True if overflow happened
- */
-/******************************************************************************/
-bool tu_fifo_overflowed(const tu_fifo_t *f) {
- return _ff_count(f->depth, f->wr_idx, f->rd_idx) > f->depth;
-}
-
// Only use in case tu_fifo_overflow() returned true!
void tu_fifo_correct_read_pointer(tu_fifo_t *f) {
_ff_lock(f->mutex_rd);
- _ff_correct_read_index(f, f->wr_idx);
+ ff_correct_read_index(f, f->wr_idx);
_ff_unlock(f->mutex_rd);
}
@@ -801,12 +702,12 @@ void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) {
uint16_t wr_idx = f->wr_idx;
uint16_t rd_idx = f->rd_idx;
- uint16_t cnt = _ff_count(f->depth, wr_idx, rd_idx);
+ uint16_t cnt = tu_ff_overflow_count(f->depth, wr_idx, rd_idx);
// Check overflow and correct if required - may happen in case a DMA wrote too fast
if (cnt > f->depth) {
_ff_lock(f->mutex_rd);
- rd_idx = _ff_correct_read_index(f, wr_idx);
+ rd_idx = ff_correct_read_index(f, wr_idx);
_ff_unlock(f->mutex_rd);
cnt = f->depth;
@@ -861,7 +762,7 @@ void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) {
void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) {
uint16_t wr_idx = f->wr_idx;
uint16_t rd_idx = f->rd_idx;
- uint16_t remain = _ff_remaining(f->depth, wr_idx, rd_idx);
+ uint16_t remain = tu_ff_remaining_local(f->depth, wr_idx, rd_idx);
if (remain == 0) {
info->len_lin = 0;
diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h
index 5cf45b2a7..c16216606 100644
--- a/src/common/tusb_fifo.h
+++ b/src/common/tusb_fifo.h
@@ -149,7 +149,7 @@ typedef enum {
} tu_fifo_access_mode_t;
//--------------------------------------------------------------------+
-//
+// Setup API
//--------------------------------------------------------------------+
bool tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable);
bool tu_fifo_clear(tu_fifo_t *f);
@@ -165,52 +165,94 @@ void tu_fifo_config_mutex(tu_fifo_t *f, osal_mutex_t wr_mutex, osal_mutex_t rd_m
#define tu_fifo_config_mutex(_f, _wr_mutex, _rd_mutex)
#endif
+//--------------------------------------------------------------------+
// Write API
+//--------------------------------------------------------------------+
uint16_t tu_fifo_write_n_access(tu_fifo_t *f, const void *data, uint16_t n, tu_fifo_access_mode_t access_mode);
bool tu_fifo_write(tu_fifo_t *f, const void *data);
TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_n(tu_fifo_t *f, const void *data, uint16_t n) {
return tu_fifo_write_n_access(f, data, n, TU_FIFO_INC_ADDR_RW8);
}
+//--------------------------------------------------------------------+
// Read API
+//--------------------------------------------------------------------+
uint16_t tu_fifo_read_n_access(tu_fifo_t *f, void *buffer, uint16_t n, tu_fifo_access_mode_t access_mode);
bool tu_fifo_read(tu_fifo_t *f, void *buffer);
TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_read_n(tu_fifo_t *f, void *buffer, uint16_t n) {
return tu_fifo_read_n_access(f, buffer, n, TU_FIFO_INC_ADDR_RW8);
}
+//--------------------------------------------------------------------+
// Peek API
+//--------------------------------------------------------------------+
uint16_t tu_fifo_peek_n_access(tu_fifo_t *f, void *p_buffer, uint16_t n, uint16_t wr_idx, uint16_t rd_idx,
tu_fifo_access_mode_t access_mode);
bool tu_fifo_peek(tu_fifo_t *f, void *p_buffer);
uint16_t tu_fifo_peek_n(tu_fifo_t *f, void *p_buffer, uint16_t n);
-uint16_t tu_fifo_count(const tu_fifo_t *f);
-uint16_t tu_fifo_remaining(const tu_fifo_t *f);
-bool tu_fifo_full(const tu_fifo_t *f);
-bool tu_fifo_overflowed(const tu_fifo_t *f);
-
-TU_ATTR_ALWAYS_INLINE static inline bool tu_fifo_empty(const tu_fifo_t *f) {
- return f->wr_idx == f->rd_idx;
-}
-
-TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_depth(const tu_fifo_t *f) {
- return f->depth;
-}
-
+//--------------------------------------------------------------------+
+// Index API
+//--------------------------------------------------------------------+
void tu_fifo_correct_read_pointer(tu_fifo_t *f);
// Pointer modifications intended to be used in combinations with DMAs.
// USE WITH CARE - NO SAFETY CHECKS CONDUCTED HERE! NOT MUTEX PROTECTED!
void tu_fifo_advance_write_pointer(tu_fifo_t *f, uint16_t n);
-void tu_fifo_advance_read_pointer (tu_fifo_t *f, uint16_t n);
+void tu_fifo_advance_read_pointer(tu_fifo_t *f, uint16_t n);
// If you want to read/write from/to the FIFO by use of a DMA, you may need to conduct two copies
// to handle a possible wrapping part. These functions deliver a pointer to start
// reading/writing from/to and a valid linear length along which no wrap occurs.
-void tu_fifo_get_read_info (tu_fifo_t *f, tu_fifo_buffer_info_t *info);
+void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info);
void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info);
+//--------------------------------------------------------------------+
+// Internal Helper Local
+// work on local copies of read/write indices in order to only access them once for re-entrancy
+//--------------------------------------------------------------------+
+// return overflowable count (index difference), which can be used to determine both fifo count and an overflow state
+TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_ff_overflow_count(uint16_t depth, uint16_t wr_idx, uint16_t rd_idx) {
+ if (wr_idx >= rd_idx) {
+ return (uint16_t)(wr_idx - rd_idx);
+ } else {
+ return (uint16_t)(2 * depth - (rd_idx - wr_idx));
+ }
+}
+
+// return remaining slot in fifo
+TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_ff_remaining_local(uint16_t depth, uint16_t wr_idx, uint16_t rd_idx) {
+ const uint16_t ovf_count = tu_ff_overflow_count(depth, wr_idx, rd_idx);
+ return (depth > ovf_count) ? (depth - ovf_count) : 0;
+}
+
+//--------------------------------------------------------------------+
+// State API
+// Following functions are reentrant since they only access read/write indices once, therefore can be used in thread and
+// ISRs context without the need of mutexes
+//--------------------------------------------------------------------+
+TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_depth(const tu_fifo_t *f) {
+ return f->depth;
+}
+
+TU_ATTR_ALWAYS_INLINE static inline bool tu_fifo_empty(const tu_fifo_t *f) {
+ return f->wr_idx == f->rd_idx;
+}
+
+// return number of items in fifo, capped to fifo's depth
+TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_count(const tu_fifo_t *f) {
+ return tu_min16(tu_ff_overflow_count(f->depth, f->wr_idx, f->rd_idx), f->depth);
+}
+
+// check if fifo is full
+TU_ATTR_ALWAYS_INLINE static inline bool tu_fifo_full(const tu_fifo_t *f) {
+ return tu_ff_overflow_count(f->depth, f->wr_idx, f->rd_idx) >= f->depth;
+}
+
+TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_remaining(const tu_fifo_t *f) {
+ return tu_ff_remaining_local(f->depth, f->wr_idx, f->rd_idx);
+}
+
#ifdef __cplusplus
}
#endif