summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhathach <[email protected]>2025-12-16 00:19:13 +0700
committerhathach <[email protected]>2025-12-16 00:19:13 +0700
commit0a9e05f47adca971eb4af8b08adf0debbc6b83db (patch)
tree3091abb1ad8c16ff18767f4239cb777ea6bf45f8
parent77fcf62f9fba99a0344ba95d78130a5c0c921e56 (diff)
make fifo access mode fixed addr work with 16 bit also
-rw-r--r--src/common/tusb_fifo.c106
-rw-r--r--src/common/tusb_fifo.h19
-rw-r--r--src/osal/osal_none.h2
-rw-r--r--test/unit-test/CMakeLists.txt2
-rw-r--r--test/unit-test/project.yml2
5 files changed, 80 insertions, 51 deletions
diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c
index e97b6ccce..450c31f57 100644
--- a/src/common/tusb_fifo.c
+++ b/src/common/tusb_fifo.c
@@ -114,40 +114,54 @@ void tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable) {
// Pull & Push
// copy data to/from fifo without updating read/write pointers
//--------------------------------------------------------------------+
-#ifdef CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_RW32
+#if CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH
+ #if CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH == 32
+ #define fixed_unaligned_write tu_unaligned_write32
+ #define fixed_unaligned_read tu_unaligned_read32
+typedef uint32_t fixed_access_item_t;
+ #elif CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH == 16
+ #define fixed_unaligned_write tu_unaligned_write16
+ #define fixed_unaligned_read tu_unaligned_read16
+typedef uint16_t fixed_access_item_t;
+ #endif
+
+enum {
+ FIXED_ACCESS_REMAINDER_MASK = sizeof(fixed_access_item_t) - 1u
+};
+
// Copy to fifo from fixed address buffer (usually a rx register) with TU_FIFO_FIXED_ADDR_RW32 mode
-static void ff_push_fixed_addr_rw32(uint8_t *ff_buf, const volatile uint32_t *reg_rx, uint16_t len) {
- // Reading full available 32 bit words from const app address
- uint16_t full_words = len >> 2;
- while (full_words--) {
- const uint32_t tmp32 = *reg_rx;
- tu_unaligned_write32(ff_buf, tmp32);
- ff_buf += 4;
+static void ff_push_fixed_addr(uint8_t *ff_buf, const volatile fixed_access_item_t *reg_rx, uint16_t len) {
+ // Reading full available 16/32-bit data from const app address
+ uint16_t n_items = len / sizeof(fixed_access_item_t);
+ while (n_items--) {
+ const fixed_access_item_t tmp = *reg_rx;
+ fixed_unaligned_write(ff_buf, tmp);
+ ff_buf += sizeof(fixed_access_item_t);
}
- // Read the remaining 1-3 bytes from const app address
- const uint8_t bytes_rem = len & 0x03;
+ // Read the remaining 1 byte (16bit) or 1-3 bytes (32bit) from const app address
+ const uint8_t bytes_rem = len & FIXED_ACCESS_REMAINDER_MASK;
if (bytes_rem) {
- const uint32_t tmp32 = *reg_rx;
- memcpy(ff_buf, &tmp32, bytes_rem);
+ const fixed_access_item_t tmp = *reg_rx;
+ memcpy(ff_buf, &tmp, bytes_rem);
}
}
// Copy from fifo to fixed address buffer (usually a tx register) with TU_FIFO_FIXED_ADDR_RW32 mode
-static void ff_pull_fixed_addr_rw32(volatile uint32_t *reg_tx, const uint8_t *ff_buf, uint16_t len) {
+static void ff_pull_fixed_addr(volatile fixed_access_item_t *reg_tx, const uint8_t *ff_buf, uint16_t len) {
// Write full available 32 bit words to const address
- uint16_t full_words = len >> 2u;
- while (full_words--) {
- *reg_tx = tu_unaligned_read32(ff_buf);
- ff_buf += 4u;
+ uint16_t n_itmes = len / sizeof(fixed_access_item_t);
+ while (n_itmes--) {
+ *reg_tx = fixed_unaligned_read(ff_buf);
+ ff_buf += sizeof(fixed_access_item_t);
}
- // Write the remaining 1-3 bytes
- const uint8_t bytes_rem = len & 0x03;
+ // Write the remaining 1 byte (16bit) or 1-3 bytes (32bit)
+ const uint8_t bytes_rem = len & FIXED_ACCESS_REMAINDER_MASK;
if (bytes_rem) {
- uint32_t tmp32 = 0u;
- memcpy(&tmp32, ff_buf, bytes_rem);
- *reg_tx = tmp32;
+ fixed_access_item_t tmp = 0u;
+ memcpy(&tmp, ff_buf, bytes_rem);
+ *reg_tx = tmp;
}
}
#endif
@@ -176,26 +190,26 @@ static void ff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint1
}
break;
-#ifdef CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_RW32
+#if CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH
case TU_FIFO_FIXED_ADDR_RW32: {
- const volatile uint32_t *reg_rx = (volatile const uint32_t *)app_buf;
+ const volatile fixed_access_item_t *reg_rx = (volatile const fixed_access_item_t *)app_buf;
if (n <= lin_count) {
// Linear only
- ff_push_fixed_addr_rw32(ff_buf, reg_rx, n * f->item_size);
+ ff_push_fixed_addr(ff_buf, reg_rx, n * f->item_size);
} else {
// Wrap around
// Write full words to linear part of buffer
- uint16_t lin_4n_bytes = lin_bytes & 0xFFFC;
- ff_push_fixed_addr_rw32(ff_buf, reg_rx, lin_4n_bytes);
- ff_buf += lin_4n_bytes;
+ uint16_t lin_nitems_bytes = lin_bytes & ~FIXED_ACCESS_REMAINDER_MASK;
+ ff_push_fixed_addr(ff_buf, reg_rx, lin_nitems_bytes);
+ ff_buf += lin_nitems_bytes;
- // There could be odd 1-3 bytes before the wrap-around boundary
- const uint8_t rem = lin_bytes & 0x03;
+ // There could be odd 1 byte (16bit) or 1-3 bytes (32bit) before the wrap-around boundary
+ const uint8_t rem = lin_bytes & FIXED_ACCESS_REMAINDER_MASK;
if (rem > 0) {
- const uint8_t remrem = (uint8_t)tu_min16(wrap_bytes, 4 - rem);
- const uint32_t tmp32 = *reg_rx;
- tu_scatter_write32(tmp32, ff_buf, rem, f->buffer, remrem);
+ const uint8_t remrem = (uint8_t)tu_min16(wrap_bytes, sizeof(fixed_access_item_t) - rem);
+ const fixed_access_item_t tmp = *reg_rx;
+ tu_scatter_write32(tmp, ff_buf, rem, f->buffer, remrem);
wrap_bytes -= remrem;
ff_buf = f->buffer + remrem; // wrap around
@@ -205,7 +219,7 @@ static void ff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint1
// Write data wrapped part
if (wrap_bytes > 0) {
- ff_push_fixed_addr_rw32(ff_buf, reg_rx, wrap_bytes);
+ ff_push_fixed_addr(ff_buf, reg_rx, wrap_bytes);
}
}
break;
@@ -240,28 +254,28 @@ static void ff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd
}
break;
-#ifdef CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_RW32
+#ifdef CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH
case TU_FIFO_FIXED_ADDR_RW32: {
- volatile uint32_t *reg_tx = (volatile uint32_t *)app_buf;
+ volatile fixed_access_item_t *reg_tx = (volatile fixed_access_item_t *)app_buf;
if (n <= lin_count) {
// Linear only
- ff_pull_fixed_addr_rw32(reg_tx, ff_buf, n * f->item_size);
+ ff_pull_fixed_addr(reg_tx, ff_buf, n * f->item_size);
} else {
// Wrap around case
// Read full words from linear part
- uint16_t lin_4n_bytes = lin_bytes & 0xFFFC;
- ff_pull_fixed_addr_rw32(reg_tx, ff_buf, lin_4n_bytes);
- ff_buf += lin_4n_bytes;
+ uint16_t lin_nitems_bytes = lin_bytes & ~FIXED_ACCESS_REMAINDER_MASK;
+ ff_pull_fixed_addr(reg_tx, ff_buf, lin_nitems_bytes);
+ ff_buf += lin_nitems_bytes;
- // There could be odd 1-3 bytes before the wrap-around boundary
- const uint8_t rem = lin_bytes & 0x03;
+ // There could be odd 1 byte (16bit) or 1-3 bytes (32bit) before the wrap-around boundary
+ const uint8_t rem = lin_bytes & FIXED_ACCESS_REMAINDER_MASK;
if (rem > 0) {
- const uint8_t remrem = (uint8_t)tu_min16(wrap_bytes, 4 - rem);
- const uint32_t scatter32 = tu_scatter_read32(ff_buf, rem, f->buffer, remrem);
+ const uint8_t remrem = (uint8_t)tu_min16(wrap_bytes, sizeof(fixed_access_item_t) - rem);
+ const fixed_access_item_t scatter = (fixed_access_item_t)tu_scatter_read32(ff_buf, rem, f->buffer, remrem);
- *reg_tx = scatter32;
+ *reg_tx = scatter;
wrap_bytes -= remrem;
ff_buf = f->buffer + remrem; // wrap around
@@ -271,7 +285,7 @@ static void ff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd
// Read data wrapped part
if (wrap_bytes > 0) {
- ff_pull_fixed_addr_rw32(reg_tx, ff_buf, wrap_bytes);
+ ff_pull_fixed_addr(reg_tx, ff_buf, wrap_bytes);
}
}
break;
diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h
index 2e2a0db6f..f58cc3fcb 100644
--- a/src/common/tusb_fifo.h
+++ b/src/common/tusb_fifo.h
@@ -49,9 +49,16 @@ extern "C" {
#define CFG_FIFO_MUTEX OSAL_MUTEX_REQUIRED
#if CFG_TUD_EDPT_DEDICATED_HWFIFO || CFG_TUH_EDPT_DEDICATED_HWFIFO
- #define CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_RW32
+ #ifndef CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH
+ #define CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH 32
+ #endif
#endif
+#ifndef CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH
+ #define CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH 0
+#endif
+
+
/* Write/Read "pointer" is in the range of: 0 .. depth - 1, and is used to get the fifo data.
* Write/Read "index" is always in the range of: 0 .. 2*depth-1
*
@@ -150,7 +157,7 @@ typedef struct {
// 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_FIXED_ADDR_RW32, // fixed address read/write by 2/4 bytes (items).
} tu_fifo_access_mode_t;
//--------------------------------------------------------------------+
@@ -205,6 +212,10 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_read_n(tu_fifo_t *f, void *
return tu_fifo_read_n_access_mode(f, buffer, n, TU_FIFO_INC_ADDR_RW8);
}
+TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_read_n_fixed_addr(tu_fifo_t *f, void *buffer, uint16_t n) {
+ return tu_fifo_read_n_access_mode(f, buffer, n, TU_FIFO_FIXED_ADDR_RW32);
+}
+
// discard first n items from fifo i.e advance read pointer by n with mutex
// return number of discarded items
uint16_t tu_fifo_discard_n(tu_fifo_t *f, uint16_t n);
@@ -218,6 +229,10 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_n(tu_fifo_t *f, const
return tu_fifo_write_n_access_mode(f, data, n, TU_FIFO_INC_ADDR_RW8);
}
+TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_n_fixed_addr(tu_fifo_t *f, const void *data, uint16_t n) {
+ return tu_fifo_write_n_access_mode(f, data, n, TU_FIFO_FIXED_ADDR_RW32);
+}
+
//--------------------------------------------------------------------+
// Internal Helper Local
// work on local copies of read/write indices in order to only access them once for re-entrancy
diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h
index 174136e38..aa6111a16 100644
--- a/src/osal/osal_none.h
+++ b/src/osal/osal_none.h
@@ -171,7 +171,7 @@ typedef osal_queue_def_t* osal_queue_t;
}
TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) {
- (void) tu_fifo_clear(&qdef->ff);
+ tu_fifo_clear(&qdef->ff);
return (osal_queue_t) qdef;
}
diff --git a/test/unit-test/CMakeLists.txt b/test/unit-test/CMakeLists.txt
index 7172f5575..3339361db 100644
--- a/test/unit-test/CMakeLists.txt
+++ b/test/unit-test/CMakeLists.txt
@@ -113,7 +113,7 @@ add_ceedling_test(
${CEEDLING_WORKDIR}/../../src/common/tusb_fifo.c
""
)
-target_compile_definitions(test_fifo PRIVATE CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_RW32=1)
+target_compile_definitions(test_fifo PRIVATE CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH=32)
add_ceedling_test(
test_usbd
diff --git a/test/unit-test/project.yml b/test/unit-test/project.yml
index d971d098d..3968faaef 100644
--- a/test/unit-test/project.yml
+++ b/test/unit-test/project.yml
@@ -128,7 +128,7 @@
:defines:
:test:
- _UNITY_TEST_
- - CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_RW32
+ - CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH=32
:release: []
# Enable to inject name of a test as a unique compilation symbol into its respective executable build.