diff options
Diffstat (limited to 'src/common')
| -rw-r--r-- | src/common/tusb_fifo.c | 133 | ||||
| -rw-r--r-- | src/common/tusb_fifo.h | 39 | ||||
| -rw-r--r-- | src/common/tusb_verify.h | 10 |
3 files changed, 83 insertions, 99 deletions
diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 450c31f57..7822b7aae 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -59,7 +59,7 @@ TU_ATTR_ALWAYS_INLINE static inline void ff_unlock(osal_mutex_t mutex) { //--------------------------------------------------------------------+ // Setup API //--------------------------------------------------------------------+ -bool tu_fifo_config(tu_fifo_t *f, void *buffer, uint16_t depth, uint16_t item_size, bool overwritable) { +bool tu_fifo_config(tu_fifo_t *f, void *buffer, uint16_t depth, 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 // only if overflow happens once (important for unsupervised DMA applications) @@ -72,7 +72,6 @@ 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 & 0x7FFFu); f->overwritable = overwritable; f->rd_idx = 0u; f->wr_idx = 0u; @@ -130,7 +129,10 @@ enum { }; // Copy to fifo from fixed address buffer (usually a rx register) with TU_FIFO_FIXED_ADDR_RW32 mode -static void ff_push_fixed_addr(uint8_t *ff_buf, const volatile fixed_access_item_t *reg_rx, uint16_t len) { +static void ff_push_access_mode(uint8_t *ff_buf, const volatile fixed_access_item_t *reg_rx, uint16_t len, + uint8_t data_stride, uint8_t addr_stride) { + (void)data_stride; + (void)addr_stride; // Reading full available 16/32-bit data from const app address uint16_t n_items = len / sizeof(fixed_access_item_t); while (n_items--) { @@ -167,86 +169,70 @@ static void ff_pull_fixed_addr(volatile fixed_access_item_t *reg_tx, const uint8 #endif // send n items to fifo WITHOUT updating write pointer -static void ff_push_n(const 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; +static void ff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint16_t wr_ptr, uint8_t data_stride, + uint8_t addr_stride) { + uint16_t lin_bytes = f->depth - wr_ptr; + uint16_t wrap_bytes = n - lin_bytes; + uint8_t *ff_buf = f->buffer + wr_ptr; - uint16_t lin_bytes = lin_count * f->item_size; - uint16_t wrap_bytes = wrap_count * f->item_size; +#if CFG_TUSB_FIFO_MULTI_BYTES_ACCESS + if (data_stride > 1) { + const volatile fixed_access_item_t *reg_rx = (volatile const fixed_access_item_t *)app_buf; + if (n <= lin_bytes) { + // Linear only + ff_push_access_mode(ff_buf, reg_rx, n, data_stride, addr_stride); + } else { + // Wrap around - // current buffer of fifo - uint8_t *ff_buf = f->buffer + (wr_ptr * f->item_size); + // Write full words to linear part of buffer + uint16_t lin_nitems_bytes = lin_bytes & ~FIXED_ACCESS_REMAINDER_MASK; + ff_push_access_mode(ff_buf, reg_rx, lin_nitems_bytes, data_stride, addr_stride); + ff_buf += lin_nitems_bytes; - switch (copy_mode) { - case TU_FIFO_INC_ADDR_RW8: - if (n <= lin_count) { - // Linear only - memcpy(ff_buf, app_buf, n * f->item_size); - } else { - // Wrap around - memcpy(ff_buf, app_buf, lin_bytes); // linear part - memcpy(f->buffer, ((const uint8_t *)app_buf) + lin_bytes, wrap_bytes); // wrapped part - } - break; + // 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, sizeof(fixed_access_item_t) - rem); + const fixed_access_item_t tmp = *reg_rx; + tu_scatter_write32(tmp, ff_buf, rem, f->buffer, remrem); -#if CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH - case TU_FIFO_FIXED_ADDR_RW32: { - 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(ff_buf, reg_rx, n * f->item_size); + wrap_bytes -= remrem; + ff_buf = f->buffer + remrem; // wrap around } else { - // Wrap around - - // Write full words to linear part of buffer - 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 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, 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 - } else { - ff_buf = f->buffer; // wrap around to beginning - } + ff_buf = f->buffer; // wrap around to beginning + } - // Write data wrapped part - if (wrap_bytes > 0) { - ff_push_fixed_addr(ff_buf, reg_rx, wrap_bytes); - } + // Write data wrapped part + if (wrap_bytes > 0) { + ff_push_access_mode(ff_buf, reg_rx, wrap_bytes, data_stride, addr_stride); } - break; } + } else #endif - - default: - break; // unknown mode + { + // single byte access + if (n <= lin_bytes) { + // Linear only + memcpy(ff_buf, app_buf, n); + } else { + // Wrap around + memcpy(ff_buf, app_buf, lin_bytes); // linear part + memcpy(f->buffer, ((const uint8_t *)app_buf) + lin_bytes, wrap_bytes); // wrapped part + } } } // get n items from fifo WITHOUT updating read pointer static void ff_pull_n(const 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 - - uint16_t lin_bytes = lin_count * f->item_size; - uint16_t wrap_bytes = wrap_count * f->item_size; - - // current buffer of fifo - const uint8_t *ff_buf = f->buffer + (rd_ptr * f->item_size); + uint16_t lin_bytes = f->depth - rd_ptr; + uint16_t wrap_bytes = n - lin_bytes; // only used if wrapped + const uint8_t *ff_buf = f->buffer + rd_ptr; switch (copy_mode) { case TU_FIFO_INC_ADDR_RW8: - if (n <= lin_count) { + if (n <= lin_bytes) { // Linear only - memcpy(app_buf, ff_buf, n * f->item_size); + memcpy(app_buf, ff_buf, n); } else { // Wrap around memcpy(app_buf, ff_buf, lin_bytes); // linear part @@ -258,9 +244,9 @@ static void ff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd case TU_FIFO_FIXED_ADDR_RW32: { volatile fixed_access_item_t *reg_tx = (volatile fixed_access_item_t *)app_buf; - if (n <= lin_count) { + if (n <= lin_bytes) { // Linear only - ff_pull_fixed_addr(reg_tx, ff_buf, n * f->item_size); + ff_pull_fixed_addr(reg_tx, ff_buf, n); } else { // Wrap around case @@ -389,7 +375,8 @@ uint16_t tu_fifo_read_n_access_mode(tu_fifo_t *f, void *buffer, uint16_t n, tu_f } // Write n items to fifo with access mode -uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, tu_fifo_access_mode_t access_mode) { +uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, uint8_t data_stride, + uint8_t addr_stride) { if (n == 0) { return 0; } @@ -415,8 +402,8 @@ uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, // function! Since it would end up in a race condition with read functions! if (n >= f->depth) { // Only copy last part - if (access_mode == TU_FIFO_INC_ADDR_RW8) { - buf8 += (n - f->depth) * f->item_size; + if (data_stride == TU_FIFO_INC_ADDR_RW8) { + buf8 += (n - f->depth); } else { // TODO should read from hw fifo to discard data, however reading an odd number could // accidentally discard data. @@ -451,7 +438,7 @@ uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, const 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, access_mode); + ff_push_n(f, buf8, n, wr_ptr, data_stride, addr_stride); f->wr_idx = advance_index(f->depth, wr_idx, n); TU_LOG(TU_FIFO_DBG, "\tnew_wr = %u\r\n", f->wr_idx); @@ -491,7 +478,7 @@ static bool ff_peek_local(tu_fifo_t *f, void *buf, uint16_t wr_idx, uint16_t rd_ } const uint16_t rd_ptr = idx2ptr(f->depth, rd_idx); - memcpy(buf, f->buffer + (rd_ptr * f->item_size), f->item_size); + memcpy(buf, f->buffer + rd_ptr, 1); return true; } @@ -526,7 +513,7 @@ bool tu_fifo_write(tu_fifo_t *f, const void *data) { ret = false; } else { const uint16_t wr_ptr = idx2ptr(f->depth, wr_idx); - memcpy(f->buffer + (wr_ptr * f->item_size), data, f->item_size); + memcpy(f->buffer + wr_ptr, data, 1); f->wr_idx = advance_index(f->depth, wr_idx, 1); ret = true; } diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index f58cc3fcb..b48cf4cea 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -58,6 +58,9 @@ extern "C" { #define CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH 0 #endif +#ifndef CFG_TUSB_FIFO_MULTI_BYTES_ACCESS + #define CFG_TUSB_FIFO_MULTI_BYTES_ACCESS 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 @@ -118,13 +121,9 @@ extern "C" { typedef struct { uint8_t *buffer; // buffer pointer uint16_t depth; // max items + bool overwritable; // ovwerwritable when full - struct TU_ATTR_PACKED { - uint16_t item_size : 15; // size of each item - bool overwritable : 1; // ovwerwritable when full - }; - - volatile uint16_t wr_idx; // write index + volatile uint16_t wr_idx; // write index TODO maybe can drop volatile volatile uint16_t rd_idx; // read index #if OSAL_MUTEX_REQUIRED @@ -141,17 +140,16 @@ typedef struct { } linear, wrapped; } tu_fifo_buffer_info_t; -#define TU_FIFO_INIT(_buffer, _depth, _type, _overwritable) \ - { \ - .buffer = _buffer, \ - .depth = _depth, \ - .item_size = sizeof(_type), \ - .overwritable = _overwritable, \ +#define TU_FIFO_INIT(_buffer, _depth, _overwritable) \ + { \ + .buffer = _buffer, \ + .depth = _depth, \ + .overwritable = _overwritable, \ } -#define TU_FIFO_DEF(_name, _depth, _type, _overwritable) \ - uint8_t _name##_buf[_depth*sizeof(_type)]; \ - tu_fifo_t _name = TU_FIFO_INIT(_name##_buf, _depth, _type, _overwritable) +#define TU_FIFO_DEF(_name, _depth, _overwritable) \ + uint8_t _name##_buf[_depth]; \ + tu_fifo_t _name = TU_FIFO_INIT(_name##_buf, _depth, _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 @@ -163,7 +161,7 @@ typedef enum { //--------------------------------------------------------------------+ // Setup API //--------------------------------------------------------------------+ -bool tu_fifo_config(tu_fifo_t *f, void *buffer, uint16_t depth, uint16_t item_size, bool overwritable); +bool tu_fifo_config(tu_fifo_t *f, void *buffer, uint16_t depth, bool overwritable); void tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable); void tu_fifo_clear(tu_fifo_t *f); @@ -223,14 +221,11 @@ uint16_t tu_fifo_discard_n(tu_fifo_t *f, uint16_t n); //--------------------------------------------------------------------+ // Write API //--------------------------------------------------------------------+ -uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, tu_fifo_access_mode_t access_mode); +uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, uint8_t data_stride, + uint8_t addr_stride); 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_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); + return tu_fifo_write_n_access_mode(f, data, n, 1, 1); } //--------------------------------------------------------------------+ diff --git a/src/common/tusb_verify.h b/src/common/tusb_verify.h index 587554e7f..c9e06361c 100644 --- a/src/common/tusb_verify.h +++ b/src/common/tusb_verify.h @@ -96,10 +96,12 @@ * - TU_VERIFY_1ARGS : return false if failed * - TU_VERIFY_2ARGS : return provided value if failed *------------------------------------------------------------------*/ -#define TU_VERIFY_DEFINE(_cond, _ret) \ - do { \ - if (!(_cond)) { return _ret; } \ - } while(0) +#define TU_VERIFY_DEFINE(_cond, _ret) \ + do { \ + if (!(_cond)) { \ + return _ret; \ + } \ + } while (0) #define TU_VERIFY_1ARGS(_cond) TU_VERIFY_DEFINE(_cond, false) #define TU_VERIFY_2ARGS(_cond, _ret) TU_VERIFY_DEFINE(_cond, _ret) |
