mirror of
https://github.com/hathach/tinyusb.git
synced 2026-02-04 20:35:27 +00:00
tusb_fifo remove item_size make it fifo of bytes
This commit is contained in:
@ -674,17 +674,17 @@ void audiod_init(void) {
|
||||
switch (i) {
|
||||
#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0
|
||||
case 0:
|
||||
tu_fifo_config(&audio->ep_in_ff, ep_in_sw_buf.buf_1, CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ, 1, true);
|
||||
tu_fifo_config(&audio->ep_in_ff, ep_in_sw_buf.buf_1, CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ, true);
|
||||
break;
|
||||
#endif
|
||||
#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0
|
||||
case 1:
|
||||
tu_fifo_config(&audio->ep_in_ff, ep_in_sw_buf.buf_2, CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ, 1, true);
|
||||
tu_fifo_config(&audio->ep_in_ff, ep_in_sw_buf.buf_2, CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ, true);
|
||||
break;
|
||||
#endif
|
||||
#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ > 0
|
||||
case 2:
|
||||
tu_fifo_config(&audio->ep_in_ff, ep_in_sw_buf.buf_3, CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ, 1, true);
|
||||
tu_fifo_config(&audio->ep_in_ff, ep_in_sw_buf.buf_3, CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ, true);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
@ -716,17 +716,17 @@ void audiod_init(void) {
|
||||
switch (i) {
|
||||
#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0
|
||||
case 0:
|
||||
tu_fifo_config(&audio->ep_out_ff, ep_out_sw_buf.buf_1, CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ, 1, true);
|
||||
tu_fifo_config(&audio->ep_out_ff, ep_out_sw_buf.buf_1, CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ, true);
|
||||
break;
|
||||
#endif
|
||||
#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0
|
||||
case 1:
|
||||
tu_fifo_config(&audio->ep_out_ff, ep_out_sw_buf.buf_2, CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ, 1, true);
|
||||
tu_fifo_config(&audio->ep_out_ff, ep_out_sw_buf.buf_2, CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ, true);
|
||||
break;
|
||||
#endif
|
||||
#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ > 0
|
||||
case 2:
|
||||
tu_fifo_config(&audio->ep_out_ff, ep_out_sw_buf.buf_3, CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ, 1, true);
|
||||
tu_fifo_config(&audio->ep_out_ff, ep_out_sw_buf.buf_3, CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ, true);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -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);
|
||||
// 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 {
|
||||
// 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
|
||||
ff_buf = f->buffer; // wrap around to beginning
|
||||
}
|
||||
break;
|
||||
|
||||
#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);
|
||||
} 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
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -157,18 +157,18 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hd
|
||||
|
||||
typedef struct {
|
||||
void (* interrupt_set)(bool enabled);
|
||||
uint16_t item_size;
|
||||
tu_fifo_t ff;
|
||||
} osal_queue_def_t;
|
||||
|
||||
typedef osal_queue_def_t* osal_queue_t;
|
||||
|
||||
// _int_set is used as mutex in OS NONE (disable/enable USB ISR)
|
||||
#define OSAL_QUEUE_DEF(_int_set, _name, _depth, _type) \
|
||||
uint8_t _name##_buf[_depth*sizeof(_type)]; \
|
||||
osal_queue_def_t _name = { \
|
||||
.interrupt_set = _int_set, \
|
||||
.ff = TU_FIFO_INIT(_name##_buf, _depth, _type, false) \
|
||||
}
|
||||
#define OSAL_QUEUE_DEF(_int_set, _name, _depth, _type) \
|
||||
uint8_t _name##_buf[_depth * sizeof(_type)]; \
|
||||
osal_queue_def_t _name = {.interrupt_set = _int_set, \
|
||||
.item_size = sizeof(_type), \
|
||||
.ff = TU_FIFO_INIT(_name##_buf, _depth * sizeof(_type), false)}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) {
|
||||
tu_fifo_clear(&qdef->ff);
|
||||
@ -184,7 +184,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, v
|
||||
(void) msec; // not used, always behave as msec = 0
|
||||
|
||||
qhdl->interrupt_set(false);
|
||||
const bool success = tu_fifo_read(&qhdl->ff, data);
|
||||
const bool success = tu_fifo_read_n(&qhdl->ff, data, qhdl->item_size);
|
||||
qhdl->interrupt_set(true);
|
||||
|
||||
return success;
|
||||
@ -195,7 +195,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void
|
||||
qhdl->interrupt_set(false);
|
||||
}
|
||||
|
||||
const bool success = tu_fifo_write(&qhdl->ff, data);
|
||||
const bool success = tu_fifo_write_n(&qhdl->ff, data, qhdl->item_size);
|
||||
|
||||
if (!in_isr) {
|
||||
qhdl->interrupt_set(true);
|
||||
|
||||
@ -47,40 +47,39 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) {
|
||||
// Spinlock API
|
||||
//--------------------------------------------------------------------+
|
||||
typedef critical_section_t osal_spinlock_t; // pico implement critical section with spinlock
|
||||
#define OSAL_SPINLOCK_DEF(_name, _int_set) \
|
||||
osal_spinlock_t _name
|
||||
#define OSAL_SPINLOCK_DEF(_name, _int_set) osal_spinlock_t _name
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline void osal_spin_init(osal_spinlock_t *ctx) {
|
||||
critical_section_init(ctx);
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline void osal_spin_lock(osal_spinlock_t *ctx, bool in_isr) {
|
||||
(void) in_isr;
|
||||
(void)in_isr;
|
||||
critical_section_enter_blocking(ctx);
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline void osal_spin_unlock(osal_spinlock_t *ctx, bool in_isr) {
|
||||
(void) in_isr;
|
||||
(void)in_isr;
|
||||
critical_section_exit(ctx);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Binary Semaphore API
|
||||
//--------------------------------------------------------------------+
|
||||
typedef struct semaphore osal_semaphore_def_t, * osal_semaphore_t;
|
||||
typedef struct semaphore osal_semaphore_def_t, *osal_semaphore_t;
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) {
|
||||
TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t *semdef) {
|
||||
sem_init(semdef, 0, 255);
|
||||
return semdef;
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_delete(osal_semaphore_t semd_hdl) {
|
||||
(void) semd_hdl;
|
||||
(void)semd_hdl;
|
||||
return true; // nothing to do
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) {
|
||||
(void) in_isr;
|
||||
(void)in_isr;
|
||||
return sem_release(sem_hdl);
|
||||
}
|
||||
|
||||
@ -96,15 +95,15 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t s
|
||||
// MUTEX API
|
||||
// Within tinyusb, mutex is never used in ISR context
|
||||
//--------------------------------------------------------------------+
|
||||
typedef struct mutex osal_mutex_def_t, * osal_mutex_t;
|
||||
typedef struct mutex osal_mutex_def_t, *osal_mutex_t;
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) {
|
||||
TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t *mdef) {
|
||||
mutex_init(mdef);
|
||||
return mdef;
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_delete(osal_mutex_t mutex_hdl) {
|
||||
(void) mutex_hdl;
|
||||
(void)mutex_hdl;
|
||||
return true; // nothing to do
|
||||
}
|
||||
|
||||
@ -123,46 +122,45 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hd
|
||||
#include "common/tusb_fifo.h"
|
||||
|
||||
typedef struct {
|
||||
tu_fifo_t ff;
|
||||
uint16_t item_size;
|
||||
tu_fifo_t ff;
|
||||
struct critical_section critsec; // osal_queue may be used in IRQs, so need critical section
|
||||
} osal_queue_def_t;
|
||||
|
||||
typedef osal_queue_def_t* osal_queue_t;
|
||||
typedef osal_queue_def_t *osal_queue_t;
|
||||
|
||||
// role device/host is used by OS NONE for mutex (disable usb isr) only
|
||||
#define OSAL_QUEUE_DEF(_int_set, _name, _depth, _type) \
|
||||
uint8_t _name##_buf[_depth*sizeof(_type)]; \
|
||||
osal_queue_def_t _name = { \
|
||||
.ff = TU_FIFO_INIT(_name##_buf, _depth, _type, false) \
|
||||
}
|
||||
#define OSAL_QUEUE_DEF(_int_set, _name, _depth, _type) \
|
||||
uint8_t _name##_buf[_depth * sizeof(_type)]; \
|
||||
osal_queue_def_t _name = {.item_size = sizeof(_type), .ff = TU_FIFO_INIT(_name##_buf, _depth * sizeof(_type), false)}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) {
|
||||
TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t *qdef) {
|
||||
critical_section_init(&qdef->critsec);
|
||||
(void) tu_fifo_clear(&qdef->ff);
|
||||
return (osal_queue_t) qdef;
|
||||
tu_fifo_clear(&qdef->ff);
|
||||
return (osal_queue_t)qdef;
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_delete(osal_queue_t qhdl) {
|
||||
osal_queue_def_t* qdef = (osal_queue_def_t*) qhdl;
|
||||
osal_queue_def_t *qdef = (osal_queue_def_t *)qhdl;
|
||||
critical_section_deinit(&qdef->critsec);
|
||||
return true;
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec) {
|
||||
(void) msec; // not used, always behave as msec = 0
|
||||
TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void *data, uint32_t msec) {
|
||||
(void)msec; // not used, always behave as msec = 0
|
||||
|
||||
critical_section_enter_blocking(&qhdl->critsec);
|
||||
bool success = tu_fifo_read(&qhdl->ff, data);
|
||||
bool success = tu_fifo_read_n(&qhdl->ff, data, qhdl->item_size);
|
||||
critical_section_exit(&qhdl->critsec);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void const* data, bool in_isr) {
|
||||
(void) in_isr;
|
||||
TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, const void *data, bool in_isr) {
|
||||
(void)in_isr;
|
||||
|
||||
critical_section_enter_blocking(&qhdl->critsec);
|
||||
bool success = tu_fifo_write(&qhdl->ff, data);
|
||||
bool success = tu_fifo_write_n(&qhdl->ff, data, qhdl->item_size);
|
||||
critical_section_exit(&qhdl->critsec);
|
||||
|
||||
return success;
|
||||
|
||||
@ -345,10 +345,9 @@ static void edpt_disable(uint8_t rhport, uint8_t ep_addr, bool stall) {
|
||||
}
|
||||
}
|
||||
|
||||
static uint16_t epin_write_tx_fifo(uint8_t rhport, uint8_t epnum) {
|
||||
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
|
||||
dwc2_dep_t* const epin = &dwc2->ep[0][epnum];
|
||||
xfer_ctl_t* const xfer = XFER_CTL_BASE(epnum, TUSB_DIR_IN);
|
||||
static uint16_t epin_write_tx_fifo(dwc2_regs_t *dwc2, uint8_t epnum) {
|
||||
dwc2_dep_t *const epin = &dwc2->ep[0][epnum];
|
||||
xfer_ctl_t *const xfer = XFER_CTL_BASE(epnum, TUSB_DIR_IN);
|
||||
|
||||
dwc2_ep_tsize_t tsiz = {.value = epin->tsiz};
|
||||
const uint16_t remain_packets = tsiz.packet_count;
|
||||
@ -438,7 +437,7 @@ static void edpt_schedule_packets(uint8_t rhport, const uint8_t epnum, const uin
|
||||
dep->diepctl = depctl.value; // enable endpoint
|
||||
|
||||
if (dir == TUSB_DIR_IN && total_bytes != 0) {
|
||||
const uint16_t xferred_bytes = epin_write_tx_fifo(rhport, epnum);
|
||||
const uint16_t xferred_bytes = epin_write_tx_fifo(dwc2, epnum);
|
||||
|
||||
// Enable TXFE interrupt if there are still data to be sent
|
||||
// EP0 only sends one packet at a time, so no need to check for EP0
|
||||
@ -689,9 +688,6 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to
|
||||
// into the USB buffer!
|
||||
bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t total_bytes, bool is_isr) {
|
||||
(void) is_isr;
|
||||
// USB buffers always work in bytes so to avoid unnecessary divisions we demand item_size = 1
|
||||
TU_ASSERT(ff->item_size == 1);
|
||||
|
||||
uint8_t const epnum = tu_edpt_number(ep_addr);
|
||||
uint8_t const dir = tu_edpt_dir(ep_addr);
|
||||
xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir);
|
||||
@ -893,7 +889,8 @@ static void handle_rxflvl_irq(uint8_t rhport) {
|
||||
if (byte_count != 0) {
|
||||
// Read packet off RxFIFO
|
||||
if (xfer->ff != NULL) {
|
||||
tu_fifo_write_n_access_mode(xfer->ff, (const void *)(uintptr_t)rx_fifo, byte_count, TU_FIFO_FIXED_ADDR_RW32);
|
||||
tu_fifo_write_n_access_mode(xfer->ff, (const void *)(uintptr_t)rx_fifo, byte_count, TU_FIFO_FIXED_ADDR_RW32,
|
||||
0);
|
||||
} else {
|
||||
dfifo_read_packet(dwc2, xfer->buffer, byte_count);
|
||||
xfer->buffer += byte_count;
|
||||
@ -967,7 +964,7 @@ static void handle_epin_slave(uint8_t rhport, uint8_t epnum, dwc2_diepint_t diep
|
||||
// - 64 bytes or
|
||||
// - Half/Empty of TX FIFO size (configured by GAHBCFG.TXFELVL)
|
||||
if (diepint_bm.txfifo_empty && tu_bit_test(dwc2->diepempmsk, epnum)) {
|
||||
epin_write_tx_fifo(rhport, epnum);
|
||||
epin_write_tx_fifo(dwc2, epnum);
|
||||
|
||||
// Turn off TXFE if all bytes are written.
|
||||
dwc2_ep_tsize_t tsiz = {.value = epin->tsiz};
|
||||
|
||||
@ -316,7 +316,7 @@ bool tu_edpt_stream_init(tu_edpt_stream_t *s, bool is_host, bool is_tx, bool ove
|
||||
#endif
|
||||
|
||||
s->is_host = is_host;
|
||||
tu_fifo_config(&s->ff, ff_buf, ff_bufsize, 1, overwritable);
|
||||
tu_fifo_config(&s->ff, ff_buf, ff_bufsize, overwritable);
|
||||
|
||||
#if OSAL_MUTEX_REQUIRED
|
||||
if (ff_buf != NULL && ff_bufsize > 0) {
|
||||
|
||||
@ -307,6 +307,7 @@
|
||||
#if defined(TUP_USBIP_DWC2)
|
||||
#if CFG_TUD_DWC2_SLAVE_ENABLE && !CFG_TUD_DWC2_DMA_ENABLE
|
||||
#define CFG_TUD_EDPT_DEDICATED_HWFIFO 1
|
||||
#define CFG_TUSB_FIFO_MULTI_BYTES_ACCESS 1
|
||||
#endif
|
||||
|
||||
#if CFG_TUH_DWC2_SLAVE_ENABLE && !CFG_TUH_DWC2_DMA_ENABLE
|
||||
|
||||
@ -129,6 +129,7 @@
|
||||
:test:
|
||||
- _UNITY_TEST_
|
||||
- CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH=32
|
||||
- CFG_TUSB_FIFO_MULTI_BYTES_ACCESS=1
|
||||
:release: []
|
||||
|
||||
# Enable to inject name of a test as a unique compilation symbol into its respective executable build.
|
||||
|
||||
@ -32,7 +32,7 @@
|
||||
|
||||
#define FIFO_SIZE 64
|
||||
uint8_t tu_ff_buf[FIFO_SIZE * sizeof(uint8_t)];
|
||||
tu_fifo_t tu_ff = TU_FIFO_INIT(tu_ff_buf, FIFO_SIZE, uint8_t, false);
|
||||
tu_fifo_t tu_ff = TU_FIFO_INIT(tu_ff_buf, FIFO_SIZE, false);
|
||||
|
||||
tu_fifo_t *ff = &tu_ff;
|
||||
tu_fifo_buffer_info_t info;
|
||||
@ -68,34 +68,6 @@ void test_normal(void) {
|
||||
}
|
||||
}
|
||||
|
||||
void test_item_size(void) {
|
||||
uint8_t ff4_buf[FIFO_SIZE * sizeof(uint32_t)];
|
||||
tu_fifo_t ff4 = TU_FIFO_INIT(ff4_buf, FIFO_SIZE, uint32_t, false);
|
||||
|
||||
uint32_t data4[2 * FIFO_SIZE];
|
||||
for (uint32_t i = 0; i < sizeof(data4) / 4; i++) {
|
||||
data4[i] = i;
|
||||
}
|
||||
|
||||
// fill up fifo
|
||||
tu_fifo_write_n(&ff4, data4, FIFO_SIZE);
|
||||
|
||||
uint32_t rd_buf4[FIFO_SIZE];
|
||||
uint16_t rd_count;
|
||||
|
||||
// read 0 -> 4
|
||||
rd_count = tu_fifo_read_n(&ff4, rd_buf4, 5);
|
||||
TEST_ASSERT_EQUAL(5, rd_count);
|
||||
TEST_ASSERT_EQUAL_UINT32_ARRAY(data4, rd_buf4, rd_count); // 0 -> 4
|
||||
|
||||
tu_fifo_write_n(&ff4, data4 + FIFO_SIZE, 5);
|
||||
|
||||
// read all 5 -> 68
|
||||
rd_count = tu_fifo_read_n(&ff4, rd_buf4, FIFO_SIZE);
|
||||
TEST_ASSERT_EQUAL(FIFO_SIZE, rd_count);
|
||||
TEST_ASSERT_EQUAL_UINT32_ARRAY(data4 + 5, rd_buf4, rd_count); // 5 -> 68
|
||||
}
|
||||
|
||||
void test_read_n(void) {
|
||||
uint16_t rd_count;
|
||||
|
||||
@ -362,7 +334,7 @@ void test_rd_idx_wrap(void) {
|
||||
uint8_t buf[10];
|
||||
uint8_t dst[10];
|
||||
|
||||
tu_fifo_config(&ff10, buf, 10, 1, 1);
|
||||
tu_fifo_config(&ff10, buf, 10, 1);
|
||||
|
||||
uint16_t n;
|
||||
|
||||
@ -431,7 +403,7 @@ void test_write_n_fixed_addr_rw32_nowrap(void) {
|
||||
|
||||
for (uint8_t n = 1; n <= 8; n++) {
|
||||
tu_fifo_clear(ff);
|
||||
uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, TU_FIFO_FIXED_ADDR_RW32);
|
||||
uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, sizeof(uint32_t), 0);
|
||||
TEST_ASSERT_EQUAL(n, written);
|
||||
TEST_ASSERT_EQUAL(n, tu_fifo_count(ff));
|
||||
|
||||
@ -453,7 +425,7 @@ void test_write_n_fixed_addr_rw32_wrapped(void) {
|
||||
ff->wr_idx = FIFO_SIZE - 3;
|
||||
ff->rd_idx = FIFO_SIZE - 3;
|
||||
|
||||
uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, TU_FIFO_FIXED_ADDR_RW32);
|
||||
uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, sizeof(uint32_t), 0);
|
||||
TEST_ASSERT_EQUAL(n, written);
|
||||
TEST_ASSERT_EQUAL(n, tu_fifo_count(ff));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user