summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
authorhathach <[email protected]>2025-11-20 18:35:28 +0700
committerhathach <[email protected]>2025-11-20 18:35:28 +0700
commit30198b2ab9e69c120e5b49c063dad3d2d3889d79 (patch)
treeb63aceb41a91b5ada7464a1311db959440a4c091 /src/common
parent409c19364b3be723b26b013efa5ab3ec1d17435a (diff)
refactor tu_fifo, add tu_fifo_write/read/peek_n_access()
Diffstat (limited to 'src/common')
-rw-r--r--src/common/tusb_fifo.c162
-rw-r--r--src/common/tusb_fifo.h32
2 files changed, 47 insertions, 147 deletions
diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c
index 5c9e586fb..a3e89bbc2 100644
--- a/src/common/tusb_fifo.c
+++ b/src/common/tusb_fifo.c
@@ -57,17 +57,6 @@ TU_ATTR_ALWAYS_INLINE static inline void _ff_unlock(osal_mutex_t mutex) {
#endif
-/** \enum tu_fifo_copy_mode_t
- * \brief Write modes intended to allow special read and write functions to be able to
- * copy data to and from USB hardware FIFOs as needed for e.g. STM32s and others
- */
-typedef enum {
- TU_FIFO_COPY_INC, ///< Copy from/to an increasing source/destination address - default mode
-#ifdef TUP_MEM_CONST_ADDR
- TU_FIFO_COPY_CST_FULL_WORDS, ///< Copy from/to a constant source/destination address - required for e.g. STM32 to write into USB hardware FIFO
-#endif
-} tu_fifo_copy_mode_t;
-
bool tu_fifo_config(tu_fifo_t *f, void *buffer, uint16_t depth, uint16_t item_size, bool overwritable) {
// Limit index space to 2*depth - this allows for a fast "modulo" calculation
// but limits the maximum depth to 2^16/2 = 2^15 and buffer overflows are detectable
@@ -147,7 +136,8 @@ static inline void _ff_push(tu_fifo_t *f, const void *app_buf, uint16_t rel) {
}
// send n items to fifo WITHOUT updating write pointer
-static void _ff_push_n(tu_fifo_t *f, const void *app_buf, uint16_t n, uint16_t wr_ptr, tu_fifo_copy_mode_t copy_mode) {
+static void _ff_push_n(tu_fifo_t *f, const void *app_buf, uint16_t n, uint16_t wr_ptr,
+ tu_fifo_access_mode_t copy_mode) {
const uint16_t lin_count = f->depth - wr_ptr;
const uint16_t wrap_count = n - lin_count;
@@ -158,7 +148,7 @@ static void _ff_push_n(tu_fifo_t *f, const void *app_buf, uint16_t n, uint16_t w
uint8_t *ff_buf = f->buffer + (wr_ptr * f->item_size);
switch (copy_mode) {
- case TU_FIFO_COPY_INC:
+ case TU_FIFO_INC_ADDR_RW8:
if (n <= lin_count) {
// Linear only
memcpy(ff_buf, app_buf, n * f->item_size);
@@ -175,7 +165,7 @@ static void _ff_push_n(tu_fifo_t *f, const void *app_buf, uint16_t n, uint16_t w
break;
#ifdef TUP_MEM_CONST_ADDR
- case TU_FIFO_COPY_CST_FULL_WORDS:
+ case TU_FIFO_FIXED_ADDR_RW32:
// Intended for hardware buffers from which it can be read word by word only
if (n <= lin_count) {
// Linear only
@@ -232,7 +222,7 @@ static inline void _ff_pull(tu_fifo_t *f, void *app_buf, uint16_t rel) {
}
// get n items from fifo WITHOUT updating read pointer
-static void _ff_pull_n(tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd_ptr, tu_fifo_copy_mode_t copy_mode) {
+static void _ff_pull_n(tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd_ptr, tu_fifo_access_mode_t copy_mode) {
const uint16_t lin_count = f->depth - rd_ptr;
const uint16_t wrap_count = n - lin_count; // only used if wrapped
@@ -243,23 +233,19 @@ static void _ff_pull_n(tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd_ptr,
uint8_t *ff_buf = f->buffer + (rd_ptr * f->item_size);
switch (copy_mode) {
- case TU_FIFO_COPY_INC:
+ case TU_FIFO_INC_ADDR_RW8:
if (n <= lin_count) {
// Linear only
memcpy(app_buf, ff_buf, n * f->item_size);
} else {
// Wrap around
-
- // Read data from linear part of buffer
- memcpy(app_buf, ff_buf, lin_bytes);
-
- // Read data wrapped part
- memcpy((uint8_t *)app_buf + lin_bytes, f->buffer, wrap_bytes);
+ memcpy(app_buf, ff_buf, lin_bytes); // linear part
+ memcpy((uint8_t *)app_buf + lin_bytes, f->buffer, wrap_bytes); // wrapped part
}
break;
#ifdef TUP_MEM_CONST_ADDR
- case TU_FIFO_COPY_CST_FULL_WORDS:
+ case TU_FIFO_FIXED_ADDR_RW32:
if (n <= lin_count) {
// Linear only
_ff_pull_const_addr(app_buf, ff_buf, n * f->item_size);
@@ -337,7 +323,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t _ff_remaining(uint16_t depth, uint1
// Advance an absolute index
// "absolute" index is only in the range of [0..2*depth)
-static uint16_t advance_index(uint16_t depth, uint16_t idx, uint16_t offset) {
+TU_ATTR_ALWAYS_INLINE static inline uint16_t advance_index(uint16_t depth, uint16_t idx, uint16_t offset) {
// 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
@@ -350,23 +336,7 @@ static uint16_t advance_index(uint16_t depth, uint16_t idx, uint16_t offset) {
return new_idx;
}
-#if 0 // not used but
-// Backward an absolute index
-static uint16_t backward_index(uint16_t depth, uint16_t idx, uint16_t offset) {
- // 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
- uint16_t new_idx = (uint16_t) (idx - offset);
- if ( (idx < new_idx) || (new_idx >= 2*depth) ) {
- uint16_t const non_used_index_space = (uint16_t) (UINT16_MAX - (2*depth-1));
- new_idx = (uint16_t) (new_idx - non_used_index_space);
- }
-
- return new_idx;
-}
-#endif
-
-// index to pointer, simply an modulo with minus.
+// index to pointer, simply a modulo with minus.
TU_ATTR_ALWAYS_INLINE static inline uint16_t idx2ptr(uint16_t depth, uint16_t idx) {
// Only run at most 3 times since index is limit in the range of [0..2*depth)
while (idx >= depth) {
@@ -416,13 +386,12 @@ static bool _tu_fifo_peek(tu_fifo_t *f, void *p_buffer, uint16_t wr_idx, uint16_
// Works on local copies of w and r
// Must be protected by mutexes since in case of an overflow read pointer gets modified
-static uint16_t _tu_fifo_peek_n(
- tu_fifo_t *f, void *p_buffer, uint16_t n, uint16_t wr_idx, uint16_t rd_idx, tu_fifo_copy_mode_t copy_mode) {
+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);
- // nothing to peek
if (cnt == 0) {
- return 0;
+ return 0; // nothing to peek
}
// Check overflow and correct if required
@@ -431,20 +400,17 @@ static uint16_t _tu_fifo_peek_n(
cnt = f->depth;
}
- // Check if we can read something at and after offset - if too less is available we read what remains
if (cnt < n) {
- n = cnt;
+ n = cnt; // limit to available count
}
- uint16_t rd_ptr = idx2ptr(f->depth, rd_idx);
-
- // Peek data
- _ff_pull_n(f, p_buffer, n, rd_ptr, copy_mode);
+ const uint16_t rd_ptr = idx2ptr(f->depth, rd_idx);
+ _ff_pull_n(f, p_buffer, n, rd_ptr, access_mode);
return n;
}
-static uint16_t _tu_fifo_write_n(tu_fifo_t *f, const void *data, uint16_t n, tu_fifo_copy_mode_t copy_mode) {
+uint16_t tu_fifo_write_n_access(tu_fifo_t *f, const void *data, uint16_t n, tu_fifo_access_mode_t access_mode) {
if (n == 0) {
return 0;
}
@@ -471,7 +437,7 @@ static uint16_t _tu_fifo_write_n(tu_fifo_t *f, const void *data, uint16_t n, tu_
// Since it would end up in a race condition with read functions!
if (n >= f->depth) {
// Only copy last part
- if (copy_mode == TU_FIFO_COPY_INC) {
+ if (access_mode == TU_FIFO_INC_ADDR_RW8) {
buf8 += (n - f->depth) * f->item_size;
} else {
// TODO should read from hw fifo to discard data, however reading an odd number could
@@ -507,7 +473,7 @@ static uint16_t _tu_fifo_write_n(tu_fifo_t *f, const void *data, uint16_t n, tu_
uint16_t wr_ptr = idx2ptr(f->depth, wr_idx);
TU_LOG(TU_FIFO_DBG, "actual_n = %u, wr_ptr = %u", n, wr_ptr);
- _ff_push_n(f, buf8, n, wr_ptr, copy_mode);
+ _ff_push_n(f, buf8, n, wr_ptr, access_mode);
f->wr_idx = advance_index(f->depth, wr_idx, n);
TU_LOG(TU_FIFO_DBG, "\tnew_wr = %u\r\n", f->wr_idx);
@@ -518,12 +484,12 @@ static uint16_t _tu_fifo_write_n(tu_fifo_t *f, const void *data, uint16_t n, tu_
return n;
}
-static uint16_t _tu_fifo_read_n(tu_fifo_t *f, void *buffer, uint16_t n, tu_fifo_copy_mode_t copy_mode) {
+uint16_t tu_fifo_read_n_access(tu_fifo_t *f, void *buffer, uint16_t n, tu_fifo_access_mode_t access_mode) {
_ff_lock(f->mutex_rd);
// Peek the data
// f->rd_idx might get modified in case of an overflow so we can not use a local variable
- n = _tu_fifo_peek_n(f, buffer, n, f->wr_idx, f->rd_idx, copy_mode);
+ n = tu_fifo_peek_n_access(f, buffer, n, f->wr_idx, f->rd_idx, access_mode);
// Advance read pointer
f->rd_idx = advance_index(f->depth, f->rd_idx, n);
@@ -653,49 +619,6 @@ bool tu_fifo_read(tu_fifo_t *f, void *buffer) {
/******************************************************************************/
/*!
- @brief This function will read n elements from the array index specified by
- the read pointer and increment the read index.
- This function checks for an overflow and corrects read pointer if required.
-
- @param[in] f
- Pointer to the FIFO buffer to manipulate
- @param[in] buffer
- The pointer to data location
- @param[in] n
- Number of element that buffer can afford
-
- @returns number of items read from the FIFO
- */
-/******************************************************************************/
-uint16_t tu_fifo_read_n(tu_fifo_t *f, void *buffer, uint16_t n) {
- return _tu_fifo_read_n(f, buffer, n, TU_FIFO_COPY_INC);
-}
-
-#ifdef TUP_MEM_CONST_ADDR
-/******************************************************************************/
-/*!
- @brief This function will read n elements from the array index specified by
- the read pointer and increment the read index.
- This function checks for an overflow and corrects read pointer if required.
- The dest address will not be incremented which is useful for writing to registers.
-
- @param[in] f
- Pointer to the FIFO buffer to manipulate
- @param[in] buffer
- The pointer to data location
- @param[in] n
- Number of element that buffer can afford
-
- @returns number of items read from the FIFO
- */
-/******************************************************************************/
-uint16_t tu_fifo_read_n_const_addr_full_words(tu_fifo_t *f, void *buffer, uint16_t n) {
- return _tu_fifo_read_n(f, buffer, n, TU_FIFO_COPY_CST_FULL_WORDS);
-}
-#endif
-
-/******************************************************************************/
-/*!
@brief Read one item without removing it from the FIFO.
This function checks for an overflow and corrects read pointer if required.
@@ -731,7 +654,7 @@ 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) {
_ff_lock(f->mutex_rd);
- uint16_t ret = _tu_fifo_peek_n(f, p_buffer, n, f->wr_idx, f->rd_idx, TU_FIFO_COPY_INC);
+ uint16_t ret = tu_fifo_peek_n_access(f, p_buffer, n, f->wr_idx, f->rd_idx, TU_FIFO_INC_ADDR_RW8);
_ff_unlock(f->mutex_rd);
return ret;
}
@@ -774,45 +697,6 @@ bool tu_fifo_write(tu_fifo_t *f, const void *data) {
/******************************************************************************/
/*!
- @brief This function will write n elements into the array index specified by
- the write pointer and increment the write index.
-
- @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
- */
-/******************************************************************************/
-uint16_t tu_fifo_write_n(tu_fifo_t *f, const void *data, uint16_t n) {
- return _tu_fifo_write_n(f, data, n, TU_FIFO_COPY_INC);
-}
-
-#ifdef TUP_MEM_CONST_ADDR
-/******************************************************************************/
-/*!
- @brief This function will write n elements into the array index specified by
- the write pointer and increment the write index. The source address will
- not be incremented which is useful for reading from registers.
-
- @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
- */
-/******************************************************************************/
-uint16_t tu_fifo_write_n_const_addr_full_words(tu_fifo_t *f, const void *data, uint16_t n) {
- return _tu_fifo_write_n(f, data, n, TU_FIFO_COPY_CST_FULL_WORDS);
-}
-#endif
-
-/******************************************************************************/
-/*!
@brief Clear the fifo read and write pointers
@param[in] f
diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h
index 9d8b864e9..5cf45b2a7 100644
--- a/src/common/tusb_fifo.h
+++ b/src/common/tusb_fifo.h
@@ -141,6 +141,16 @@ typedef struct {
uint8_t _name##_buf[_depth*sizeof(_type)]; \
tu_fifo_t _name = TU_FIFO_INIT(_name##_buf, _depth, _type, _overwritable)
+// Write modes intended to allow special read and write functions to be able to
+// copy data to and from USB hardware FIFOs as needed for e.g. STM32s and others
+typedef enum {
+ TU_FIFO_INC_ADDR_RW8, // increased address read/write by bytes - normal (default) mode
+ TU_FIFO_FIXED_ADDR_RW32, // fixed address read/write by 4 bytes (word). Used for STM32 access into USB hardware FIFO
+} tu_fifo_access_mode_t;
+
+//--------------------------------------------------------------------+
+//
+//--------------------------------------------------------------------+
bool tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable);
bool tu_fifo_clear(tu_fifo_t *f);
bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable);
@@ -155,17 +165,23 @@ 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
-bool tu_fifo_write(tu_fifo_t *f, void const *data);
-uint16_t tu_fifo_write_n(tu_fifo_t *f, const void *data, uint16_t n);
+// 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);
-uint16_t tu_fifo_read_n(tu_fifo_t *f, void *buffer, uint16_t n);
-
-#ifdef TUP_MEM_CONST_ADDR
-uint16_t tu_fifo_write_n_const_addr_full_words(tu_fifo_t *f, const void *data, uint16_t n);
-uint16_t tu_fifo_read_n_const_addr_full_words(tu_fifo_t *f, void *buffer, uint16_t n);
-#endif
+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);