From 03f974c9b92bf9e0fc6e74ab4d15ad77a4a8b339 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 23 Apr 2021 10:27:48 +0200 Subject: [PATCH 01/15] Implement functions to allow for DMA usage in audio driver. - Add tud_audio_n_get_ep_out_ff(), tud_audio_n_get_ep_in_ff(), tud_audio_n_get_rx_support_ff(), and tud_audio_n_get_tx_support_ff() - Change get_linear_read/write_info() to return linear and wrapped part at once - Adjusted affected code in audio_device.c and tested with audio_4_channel. --- src/class/audio/audio_device.c | 77 +++++++++++-------- src/class/audio/audio_device.h | 29 +++++++ src/common/tusb_fifo.c | 35 +++++---- src/common/tusb_fifo.h | 6 +- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 4 +- 5 files changed, 103 insertions(+), 48 deletions(-) diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 0a60d9ee5..f96878b5b 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -447,27 +447,39 @@ bool tud_audio_n_clear_ep_out_ff(uint8_t func_id) return tu_fifo_clear(&_audiod_fct[func_id].ep_out_ff); } +tu_fifo_t* tud_audio_n_get_ep_out_ff(uint8_t func_id) +{ + if(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL) return &_audiod_fct[func_id].ep_out_ff; + return NULL; +} + #endif #if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT // Delete all content in the support RX FIFOs bool tud_audio_n_clear_rx_support_ff(uint8_t func_id, uint8_t ff_idx) { - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL, ff_idx < _audiod_fct[func_id].n_rx_supp_ff); + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_rx_supp_ff); return tu_fifo_clear(&_audiod_fct[func_id].rx_supp_ff[ff_idx]); } uint16_t tud_audio_n_available_support_ff(uint8_t func_id, uint8_t ff_idx) { - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL, ff_idx < _audiod_fct[func_id].n_rx_supp_ff); + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_rx_supp_ff); return tu_fifo_count(&_audiod_fct[func_id].rx_supp_ff[ff_idx]); } uint16_t tud_audio_n_read_support_ff(uint8_t func_id, uint8_t ff_idx, void* buffer, uint16_t bufsize) { - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL, ff_idx < _audiod_fct[func_id].n_rx_supp_ff); + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_rx_supp_ff); return tu_fifo_read_n(&_audiod_fct[func_id].rx_supp_ff[ff_idx], buffer, bufsize); } + +tu_fifo_t* tud_audio_n_get_rx_support_ff(uint8_t func_id, uint8_t ff_idx) +{ + if(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_rx_supp_ff) return &_audiod_fct[func_id].rx_supp_ff[ff_idx]; + return NULL; +} #endif // This function is called once an audio packet is received by the USB and is responsible for putting data from USB memory into EP_OUT_FIFO (or support FIFOs + decoding of received stream into audio channels). @@ -635,32 +647,26 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, u uint8_t cnt_ff; // Decode - void * dst; + void * dst, * dst_wrap; uint8_t * src; uint8_t * dst_end; - uint16_t len; + uint16_t len, len_wrap; for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) { src = &audio->lin_buf_out[cnt_ff*audio->n_channels_per_ff_rx * audio->n_bytes_per_sampe_rx]; - - len = tu_fifo_get_linear_write_info(&audio->rx_supp_ff[cnt_ff], 0, &dst, nBytesPerFFToRead); - tu_fifo_advance_write_pointer(&audio->rx_supp_ff[cnt_ff], len); + len = tu_fifo_get_linear_write_info(&audio->rx_supp_ff[cnt_ff], 0, nBytesPerFFToRead, &dst, &len_wrap, &dst_wrap); dst_end = dst + len; - src = audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, dst, dst_end, src, n_ff_used); // Handle wrapped part of FIFO - if (len < nBytesPerFFToRead) + if (len_wrap != 0) { - len = tu_fifo_get_linear_write_info(&audio->rx_supp_ff[cnt_ff], 0, &dst, nBytesPerFFToRead - len); - tu_fifo_advance_write_pointer(&audio->rx_supp_ff[cnt_ff], len); - - dst_end = dst + len; - - audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, dst, dst_end, src, n_ff_used); + dst_end = dst_wrap + len_wrap; + audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, dst_wrap, dst_end, src, n_ff_used); } + tu_fifo_advance_write_pointer(&audio->rx_supp_ff[cnt_ff], len + len_wrap); } // Number of bytes should be a multiple of CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX but checking makes no sense - no way to correct it @@ -699,9 +705,16 @@ bool tud_audio_n_clear_ep_in_ff(uint8_t func_id) // Del return tu_fifo_clear(&_audiod_fct[func_id].ep_in_ff); } +tu_fifo_t* tud_audio_n_get_ep_in_ff(uint8_t func_id) +{ + if(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL) return &_audiod_fct[func_id].ep_in_ff; + return NULL; +} + #endif #if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN + uint16_t tud_audio_n_flush_tx_support_ff(uint8_t func_id) // Force all content in the support TX FIFOs to be written into linear buffer and schedule a transmit { TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); @@ -719,15 +732,22 @@ uint16_t tud_audio_n_flush_tx_support_ff(uint8_t func_id) // For bool tud_audio_n_clear_tx_support_ff(uint8_t func_id, uint8_t ff_idx) { - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL, ff_idx < _audiod_fct[func_id].n_tx_supp_ff); + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_tx_supp_ff); return tu_fifo_clear(&_audiod_fct[func_id].tx_supp_ff[ff_idx]); } uint16_t tud_audio_n_write_support_ff(uint8_t func_id, uint8_t ff_idx, const void * data, uint16_t len) { - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL, ff_idx < _audiod_fct[func_id].n_tx_supp_ff); + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_tx_supp_ff); return tu_fifo_write_n(&_audiod_fct[func_id].tx_supp_ff[ff_idx], data, len); } + +tu_fifo_t* tud_audio_n_get_tx_support_ff(uint8_t func_id, uint8_t ff_idx) +{ + if(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_tx_supp_ff) return &_audiod_fct[func_id].tx_supp_ff[ff_idx]; + return NULL; +} + #endif @@ -751,6 +771,7 @@ uint16_t tud_audio_int_ctr_n_write(uint8_t func_id, uint8_t const* buffer, uint1 return true; } + #endif @@ -952,32 +973,28 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi nBytesPerFFToSend = (nBytesPerFFToSend / nBytesToCopy) * nBytesToCopy; // Encode - void * src; + void * src, * src_wrap; uint8_t * dst; uint8_t * src_end; - uint16_t len; + uint16_t len, len_wrap; for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) { dst = &audio->lin_buf_in[cnt_ff*audio->n_channels_per_ff_tx*audio->n_bytes_per_sampe_tx]; - len = tu_fifo_get_linear_read_info(&audio->tx_supp_ff[cnt_ff], 0, &src, nBytesPerFFToSend); - tu_fifo_advance_read_pointer(&audio->tx_supp_ff[cnt_ff], len); + len = tu_fifo_get_linear_read_info(&audio->tx_supp_ff[cnt_ff], 0, nBytesPerFFToSend, &src, &len_wrap, &src_wrap); src_end = src + len; - dst = audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, src, src_end, dst, n_ff_used); // Handle wrapped part of FIFO - if (len < nBytesPerFFToSend) + if (len_wrap != 0) { - len = tu_fifo_get_linear_read_info(&audio->tx_supp_ff[cnt_ff], 0, &src, nBytesPerFFToSend - len); - tu_fifo_advance_read_pointer(&audio->tx_supp_ff[cnt_ff], len); - - src_end = src + len; - - audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, src, src_end, dst, n_ff_used); + src_end = src_wrap + len_wrap; + audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, src_wrap, src_end, dst, n_ff_used); } + + tu_fifo_advance_read_pointer(&audio->tx_supp_ff[cnt_ff], len + len_wrap); } return nBytesPerFFToSend * n_ff_used; diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index c070e48c2..66cc29739 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -33,6 +33,7 @@ #include "device/usbd.h" #include "audio.h" +#include "tusb_fifo.h" //--------------------------------------------------------------------+ // Class Driver Configuration @@ -364,23 +365,27 @@ bool tud_audio_n_mounted (uint8_t func_id); uint16_t tud_audio_n_available (uint8_t func_id); uint16_t tud_audio_n_read (uint8_t func_id, void* buffer, uint16_t bufsize); bool tud_audio_n_clear_ep_out_ff (uint8_t func_id); // Delete all content in the EP OUT FIFO +tu_fifo_t* tud_audio_n_get_ep_out_ff (uint8_t func_id); #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING bool tud_audio_n_clear_rx_support_ff (uint8_t func_id, uint8_t ff_idx); // Delete all content in the support RX FIFOs uint16_t tud_audio_n_available_support_ff (uint8_t func_id, uint8_t ff_idx); uint16_t tud_audio_n_read_support_ff (uint8_t func_id, uint8_t ff_idx, void* buffer, uint16_t bufsize); +tu_fifo_t* tud_audio_n_get_rx_support_ff (uint8_t func_id, uint8_t ff_idx); #endif #if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING uint16_t tud_audio_n_write (uint8_t func_id, const void * data, uint16_t len); bool tud_audio_n_clear_ep_in_ff (uint8_t func_id); // Delete all content in the EP IN FIFO +tu_fifo_t* tud_audio_n_get_ep_in_ff (uint8_t func_id); #endif #if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING uint16_t tud_audio_n_flush_tx_support_ff (uint8_t func_id); // Force all content in the support TX FIFOs to be written into EP SW FIFO bool tud_audio_n_clear_tx_support_ff (uint8_t func_id, uint8_t ff_idx); uint16_t tud_audio_n_write_support_ff (uint8_t func_id, uint8_t ff_idx, const void * data, uint16_t len); +tu_fifo_t* tud_audio_n_get_tx_support_ff (uint8_t func_id, uint8_t ff_idx); #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN @@ -399,12 +404,14 @@ static inline bool tud_audio_mounted (void); static inline uint16_t tud_audio_available (void); static inline bool tud_audio_clear_ep_out_ff (void); // Delete all content in the EP OUT FIFO static inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize); +static inline tu_fifo_t* tud_audio_get_ep_out_ff (void); #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING static inline bool tud_audio_clear_rx_support_ff (uint8_t ff_idx); static inline uint16_t tud_audio_available_support_ff (uint8_t ff_idx); static inline uint16_t tud_audio_read_support_ff (uint8_t ff_idx, void* buffer, uint16_t bufsize); +static inline tu_fifo_t* tud_audio_get_rx_support_ff (uint8_t ff_idx); #endif // TX API @@ -412,12 +419,14 @@ static inline uint16_t tud_audio_read_support_ff (uint8_t ff_idx, voi #if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING static inline uint16_t tud_audio_write (const void * data, uint16_t len); static inline bool tud_audio_clear_ep_in_ff (void); +static inline tu_fifo_t* tud_audio_get_ep_in_ff (void); #endif #if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING static inline uint16_t tud_audio_flush_tx_support_ff (void); static inline uint16_t tud_audio_clear_tx_support_ff (uint8_t ff_idx); static inline uint16_t tud_audio_write_support_ff (uint8_t ff_idx, const void * data, uint16_t len); +static inline tu_fifo_t* tud_audio_get_tx_support_ff (uint8_t ff_idx); #endif // INT CTR API @@ -514,6 +523,11 @@ static inline bool tud_audio_clear_ep_out_ff(void) return tud_audio_n_clear_ep_out_ff(0); } +static inline tu_fifo_t* tud_audio_get_ep_out_ff(void) +{ + return tud_audio_n_get_ep_out_ff(0); +} + #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING @@ -533,6 +547,11 @@ static inline uint16_t tud_audio_read_support_ff(uint8_t ff_idx, void* buffer, u return tud_audio_n_read_support_ff(0, ff_idx, buffer, bufsize); } +static inline tu_fifo_t* tud_audio_get_rx_support_ff(uint8_t ff_idx) +{ + return tud_audio_n_get_rx_support_ff(0, ff_idx); +} + #endif // TX API @@ -549,6 +568,11 @@ static inline bool tud_audio_clear_ep_in_ff(void) return tud_audio_n_clear_ep_in_ff(0); } +static inline tu_fifo_t* tud_audio_get_ep_in_ff(void) +{ + return tud_audio_n_get_ep_in_ff(0); +} + #endif #if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING @@ -568,6 +592,11 @@ static inline uint16_t tud_audio_write_support_ff(uint8_t ff_idx, const void * d return tud_audio_n_write_support_ff(0, ff_idx, data, len); } +static inline tu_fifo_t* tud_audio_get_tx_support_ff(uint8_t ff_idx) +{ + return tud_audio_n_get_tx_support_ff(0, ff_idx); +} + #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 098d54801..3bca8397b 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -905,7 +905,7 @@ void tu_fifo_advance_read_pointer(tu_fifo_t *f, uint16_t n) Length of linear part IN ITEMS, if zero corresponding pointer ptr is invalid */ /******************************************************************************/ -uint16_t tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, void **ptr, uint16_t n) +uint16_t tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, uint16_t n, void **ptr_lin, uint16_t *len_wrap, void **ptr_wrap) { // Operate on temporary values in case they change in between uint16_t w = f->wr_idx, r = f->rd_idx; @@ -933,23 +933,26 @@ uint16_t tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, void **ptr, w = get_relative_pointer(f, w, 0); r = get_relative_pointer(f, r, offset); + // Copy pointer to buffer to start reading from + *ptr_lin = &f->buffer[r]; + *ptr_wrap = f->buffer; + // Check if there is a wrap around necessary uint16_t len; if (w > r) { + // Non wrapping case len = w - r; + len = tu_min16(n, len); // Limit to required length + *len_wrap = 0; } else { len = f->depth - r; // Also the case if FIFO was full + len = tu_min16(n, len); + *len_wrap = n-len; // n was already limited to what is available } - // Limit to required length - len = tu_min16(n, len); - - // Copy pointer to buffer to start reading from - *ptr = &f->buffer[r]; - return len; } @@ -976,7 +979,7 @@ uint16_t tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, void **ptr, Length of linear part IN ITEMS, if zero corresponding pointer ptr is invalid */ /******************************************************************************/ -uint16_t tu_fifo_get_linear_write_info(tu_fifo_t *f, uint16_t offset, void **ptr, uint16_t n) +uint16_t tu_fifo_get_linear_write_info(tu_fifo_t *f, uint16_t offset, uint16_t n, void **ptr_lin, uint16_t *len_wrap, void **ptr_wrap) { uint16_t w = f->wr_idx, r = f->rd_idx; uint16_t free = _tu_fifo_remaining(f, w, r); @@ -1004,22 +1007,26 @@ uint16_t tu_fifo_get_linear_write_info(tu_fifo_t *f, uint16_t offset, void **ptr // Get relative pointers w = get_relative_pointer(f, w, offset); r = get_relative_pointer(f, r, 0); + + // Copy pointer to buffer to start writing to + *ptr_lin = &f->buffer[w]; + *ptr_wrap = f->buffer; // Always start of buffer + uint16_t len; if (w < r) { + // Non wrapping case len = r-w; + len = tu_min16(n, len); // Limit to required length + *len_wrap = 0; } else { len = f->depth - w; + len = tu_min16(n, len); // Limit to required length + *len_wrap = n-len; // Remaining length - n already was limited to free or FIFO depth } - // Limit to required length - len = tu_min16(n, len); - - // Copy pointer to buffer to start reading from - *ptr = &f->buffer[w]; - return len; } diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index b2d0b5be9..28998ad24 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -134,8 +134,10 @@ void tu_fifo_advance_read_pointer (tu_fifo_t *f, uint16_t n); // This functions deliver a pointer to start reading/writing from/to and a valid linear length along which no wrap occurs. // In case not all of your data is available within one read/write, update the read/write pointer by // tu_fifo_advance_read_pointer()/tu_fifo_advance_write_pointer and conduct a second read/write operation -uint16_t tu_fifo_get_linear_read_info (tu_fifo_t *f, uint16_t offset, void **ptr, uint16_t n); -uint16_t tu_fifo_get_linear_write_info (tu_fifo_t *f, uint16_t offset, void **ptr, uint16_t n); +// TODO - update comments + +uint16_t tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, uint16_t n, void **ptr_lin, uint16_t *len_wrap, void **ptr_wrap); +uint16_t tu_fifo_get_linear_write_info(tu_fifo_t *f, uint16_t offset, uint16_t n, void **ptr_lin, uint16_t *len_wrap, void **ptr_wrap); static inline bool tu_fifo_peek(tu_fifo_t* f, void * p_buffer) { diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index b8b0fc104..dd0d76c1f 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -993,7 +993,7 @@ static bool dcd_write_packet_memory_ff(tu_fifo_t * ff, uint16_t dst, uint16_t wN // Since we copy from a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies // Check for first linear part void * src; - uint16_t len = tu_fifo_get_linear_read_info(ff, 0, &src, wNBytes); // We want to read from the FIFO + uint16_t len = tu_fifo_get_linear_read_info(ff, 0, &src, wNBytes); // We want to read from the FIFO - THIS FUNCTION CHANGED!!! TU_VERIFY(len && dcd_write_packet_memory(dst, src, len)); // and write it into the PMA tu_fifo_advance_read_pointer(ff, len); @@ -1075,7 +1075,7 @@ static bool dcd_read_packet_memory_ff(tu_fifo_t * ff, uint16_t src, uint16_t wNB // Since we copy into a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies // Check for first linear part void * dst; - uint16_t len = tu_fifo_get_linear_write_info(ff, 0, &dst, wNBytes); + uint16_t len = tu_fifo_get_linear_write_info(ff, 0, &dst, wNBytes); // THIS FUNCTION CHANGED!!!! TU_VERIFY(len && dcd_read_packet_memory(dst, src, len)); tu_fifo_advance_write_pointer(ff, len); From 4dd1f1f3b50592d71fefcd8fb149322fad5a8493 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 23 Apr 2021 10:32:22 +0200 Subject: [PATCH 02/15] Fix include path in audio_device.h --- src/class/audio/audio_device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 66cc29739..c5f8967e4 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -33,7 +33,7 @@ #include "device/usbd.h" #include "audio.h" -#include "tusb_fifo.h" +#include "common/tusb_fifo.h" //--------------------------------------------------------------------+ // Class Driver Configuration From a98d0217a05129b36d2eef76f36b986c31f84e92 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 23 Apr 2021 10:47:22 +0200 Subject: [PATCH 03/15] Init len_wrap = 0 to fix compiler complains. --- src/class/audio/audio_device.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index f96878b5b..4fdb58333 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -650,7 +650,7 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, u void * dst, * dst_wrap; uint8_t * src; uint8_t * dst_end; - uint16_t len, len_wrap; + uint16_t len, len_wrap = 0; for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) { @@ -976,7 +976,7 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi void * src, * src_wrap; uint8_t * dst; uint8_t * src_end; - uint16_t len, len_wrap; + uint16_t len, len_wrap = 0; // Give len_wrap a value such that compiler does not complain - although it gets initialized in any case... for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) { From 7072f0155e994005d8a0ccf5658f765df8a443b8 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 23 Apr 2021 11:48:54 +0200 Subject: [PATCH 04/15] Change tu_fifo_get_linear_write/read_info() to return a struct Compilers always complain that variables set by function via pointer might be uninitialized so to avoid that return values are now delivered via struct. --- src/class/audio/audio_device.c | 36 ++++++++++++------------ src/common/tusb_fifo.c | 50 ++++++++++++++++------------------ src/common/tusb_fifo.h | 12 ++++++-- 3 files changed, 51 insertions(+), 47 deletions(-) diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 4fdb58333..25bf9e2d9 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -647,26 +647,26 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, u uint8_t cnt_ff; // Decode - void * dst, * dst_wrap; uint8_t * src; uint8_t * dst_end; - uint16_t len, len_wrap = 0; + + tu_fifo_linear_wr_info info; for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) { src = &audio->lin_buf_out[cnt_ff*audio->n_channels_per_ff_rx * audio->n_bytes_per_sampe_rx]; - len = tu_fifo_get_linear_write_info(&audio->rx_supp_ff[cnt_ff], 0, nBytesPerFFToRead, &dst, &len_wrap, &dst_wrap); + info = tu_fifo_get_linear_write_info(&audio->rx_supp_ff[cnt_ff], 0, nBytesPerFFToRead); - dst_end = dst + len; - src = audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, dst, dst_end, src, n_ff_used); + dst_end = info.ptr_lin + info.len_lin; + src = audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, info.ptr_lin, dst_end, src, n_ff_used); // Handle wrapped part of FIFO - if (len_wrap != 0) + if (info.len_wrap != 0) { - dst_end = dst_wrap + len_wrap; - audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, dst_wrap, dst_end, src, n_ff_used); + dst_end = info.ptr_wrap + info.len_wrap; + audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, info.ptr_wrap, dst_end, src, n_ff_used); } - tu_fifo_advance_write_pointer(&audio->rx_supp_ff[cnt_ff], len + len_wrap); + tu_fifo_advance_write_pointer(&audio->rx_supp_ff[cnt_ff], info.len_lin + info.len_wrap); } // Number of bytes should be a multiple of CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX but checking makes no sense - no way to correct it @@ -973,28 +973,28 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi nBytesPerFFToSend = (nBytesPerFFToSend / nBytesToCopy) * nBytesToCopy; // Encode - void * src, * src_wrap; uint8_t * dst; uint8_t * src_end; - uint16_t len, len_wrap = 0; // Give len_wrap a value such that compiler does not complain - although it gets initialized in any case... + + tu_fifo_linear_wr_info info; for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) { dst = &audio->lin_buf_in[cnt_ff*audio->n_channels_per_ff_tx*audio->n_bytes_per_sampe_tx]; - len = tu_fifo_get_linear_read_info(&audio->tx_supp_ff[cnt_ff], 0, nBytesPerFFToSend, &src, &len_wrap, &src_wrap); + info = tu_fifo_get_linear_read_info(&audio->tx_supp_ff[cnt_ff], 0, nBytesPerFFToSend); - src_end = src + len; - dst = audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, src, src_end, dst, n_ff_used); + src_end = info.ptr_lin + info.len_lin; + dst = audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, info.ptr_lin, src_end, dst, n_ff_used); // Handle wrapped part of FIFO - if (len_wrap != 0) + if (info.len_wrap != 0) { - src_end = src_wrap + len_wrap; - audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, src_wrap, src_end, dst, n_ff_used); + src_end = info.ptr_wrap + info.len_wrap; + audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, info.ptr_wrap, src_end, dst, n_ff_used); } - tu_fifo_advance_read_pointer(&audio->tx_supp_ff[cnt_ff], len + len_wrap); + tu_fifo_advance_read_pointer(&audio->tx_supp_ff[cnt_ff], info.len_lin + info.len_wrap); } return nBytesPerFFToSend * n_ff_used; diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 3bca8397b..75dae0906 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -905,7 +905,7 @@ void tu_fifo_advance_read_pointer(tu_fifo_t *f, uint16_t n) Length of linear part IN ITEMS, if zero corresponding pointer ptr is invalid */ /******************************************************************************/ -uint16_t tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, uint16_t n, void **ptr_lin, uint16_t *len_wrap, void **ptr_wrap) +tu_fifo_linear_wr_info tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, uint16_t n) { // Operate on temporary values in case they change in between uint16_t w = f->wr_idx, r = f->rd_idx; @@ -922,8 +922,10 @@ uint16_t tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, uint16_t n, cnt = f->depth; } + tu_fifo_linear_wr_info info = {0,0,NULL,NULL}; + // Skip beginning of buffer - if (cnt == 0 || offset >= cnt) return 0; + if (cnt == 0 || offset >= cnt) return info; // Check if we can read something at and after offset - if too less is available we read what remains cnt -= offset; @@ -934,26 +936,22 @@ uint16_t tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, uint16_t n, r = get_relative_pointer(f, r, offset); // Copy pointer to buffer to start reading from - *ptr_lin = &f->buffer[r]; - *ptr_wrap = f->buffer; + info.ptr_lin = &f->buffer[r]; + info.ptr_wrap = f->buffer; // Check if there is a wrap around necessary - uint16_t len; - if (w > r) { // Non wrapping case - len = w - r; - len = tu_min16(n, len); // Limit to required length - *len_wrap = 0; + info.len_lin = tu_min16(n, w - r); // Limit to required length + info.len_wrap = 0; } else { - len = f->depth - r; // Also the case if FIFO was full - len = tu_min16(n, len); - *len_wrap = n-len; // n was already limited to what is available + info.len_lin = tu_min16(n, f->depth - r); // Also the case if FIFO was full + info.len_wrap = n-info.len_lin; // n was already limited to what is available } - return len; + return info; } /******************************************************************************/ @@ -979,11 +977,13 @@ uint16_t tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, uint16_t n, Length of linear part IN ITEMS, if zero corresponding pointer ptr is invalid */ /******************************************************************************/ -uint16_t tu_fifo_get_linear_write_info(tu_fifo_t *f, uint16_t offset, uint16_t n, void **ptr_lin, uint16_t *len_wrap, void **ptr_wrap) +tu_fifo_linear_wr_info tu_fifo_get_linear_write_info(tu_fifo_t *f, uint16_t offset, uint16_t n) { uint16_t w = f->wr_idx, r = f->rd_idx; uint16_t free = _tu_fifo_remaining(f, w, r); + tu_fifo_linear_wr_info info = {0,0,NULL,NULL}; + if (!f->overwritable) { // Not overwritable limit up to full @@ -992,7 +992,7 @@ uint16_t tu_fifo_get_linear_write_info(tu_fifo_t *f, uint16_t offset, uint16_t n else if (n >= f->depth) { // If overwrite is allowed it must be less than or equal to 2 x buffer length, otherwise the overflow can not be resolved by the read functions - TU_VERIFY(n <= 2*f->depth); + if(n > 2*f->depth) return info; n = f->depth; // We start writing at the read pointer's position since we fill the complete @@ -1002,31 +1002,27 @@ uint16_t tu_fifo_get_linear_write_info(tu_fifo_t *f, uint16_t offset, uint16_t n } // Check if there is room to write to - if (free == 0 || offset >= free) return 0; + if (free == 0 || offset >= free) return info; // Get relative pointers w = get_relative_pointer(f, w, offset); r = get_relative_pointer(f, r, 0); // Copy pointer to buffer to start writing to - *ptr_lin = &f->buffer[w]; - *ptr_wrap = f->buffer; // Always start of buffer - - uint16_t len; + info.ptr_lin = &f->buffer[w]; + info.ptr_wrap = f->buffer; // Always start of buffer if (w < r) { // Non wrapping case - len = r-w; - len = tu_min16(n, len); // Limit to required length - *len_wrap = 0; + info.len_lin = tu_min16(n, r-w); // Limit to required length + info.len_wrap = 0; } else { - len = f->depth - w; - len = tu_min16(n, len); // Limit to required length - *len_wrap = n-len; // Remaining length - n already was limited to free or FIFO depth + info.len_lin = tu_min16(n, f->depth - w); // Limit to required length + info.len_wrap = n-info.len_lin; // Remaining length - n already was limited to free or FIFO depth } - return len; + return info; } diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 28998ad24..c23f25723 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -80,6 +80,14 @@ typedef struct } tu_fifo_t; +typedef struct +{ + uint16_t len_lin ; ///< linear length in item size + uint16_t len_wrap ; ///< wrapped length in item size + void * ptr_lin ; ///< linear part start pointer + void * ptr_wrap ; ///< wrapped part start pointer +} tu_fifo_linear_wr_info; + #define TU_FIFO_INIT(_buffer, _depth, _type, _overwritable) \ { \ .buffer = _buffer, \ @@ -136,8 +144,8 @@ void tu_fifo_advance_read_pointer (tu_fifo_t *f, uint16_t n); // tu_fifo_advance_read_pointer()/tu_fifo_advance_write_pointer and conduct a second read/write operation // TODO - update comments -uint16_t tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, uint16_t n, void **ptr_lin, uint16_t *len_wrap, void **ptr_wrap); -uint16_t tu_fifo_get_linear_write_info(tu_fifo_t *f, uint16_t offset, uint16_t n, void **ptr_lin, uint16_t *len_wrap, void **ptr_wrap); +tu_fifo_linear_wr_info tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, uint16_t n); +tu_fifo_linear_wr_info tu_fifo_get_linear_write_info(tu_fifo_t *f, uint16_t offset, uint16_t n); static inline bool tu_fifo_peek(tu_fifo_t* f, void * p_buffer) { From c9177246d25b8bd6972a947da4f6d5a39f86f7c6 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 28 Apr 2021 12:31:24 +0700 Subject: [PATCH 05/15] temporarily fix include recusrive loop --- src/class/audio/audio_device.c | 4 ++-- src/class/audio/audio_device.h | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 25bf9e2d9..8615b2468 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -55,9 +55,9 @@ //--------------------------------------------------------------------+ // INCLUDE //--------------------------------------------------------------------+ -#include "audio_device.h" -#include "class/audio/audio.h" #include "device/usbd_pvt.h" +#include "audio_device.h" +//#include "common/tusb_fifo.h" //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index c5f8967e4..b8e6ef9c0 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -33,7 +33,6 @@ #include "device/usbd.h" #include "audio.h" -#include "common/tusb_fifo.h" //--------------------------------------------------------------------+ // Class Driver Configuration From 8f72c97f7b0fa14badbc36497fba2c6d21cb59d0 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 30 Apr 2021 12:59:12 +0200 Subject: [PATCH 06/15] Change read infos to pointer type --- src/class/audio/audio_device.c | 50 ++++++++++--------- src/common/tusb_fifo.c | 88 +++++++++++++++++----------------- src/common/tusb_fifo.h | 6 +-- 3 files changed, 76 insertions(+), 68 deletions(-) diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 8615b2468..f19f8f6fe 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -650,23 +650,26 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, u uint8_t * src; uint8_t * dst_end; - tu_fifo_linear_wr_info info; + tu_fifo_buffer_info_t info; for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) { - src = &audio->lin_buf_out[cnt_ff*audio->n_channels_per_ff_rx * audio->n_bytes_per_sampe_rx]; - info = tu_fifo_get_linear_write_info(&audio->rx_supp_ff[cnt_ff], 0, nBytesPerFFToRead); + tu_fifo_get_write_info(&audio->rx_supp_ff[cnt_ff], &info, nBytesPerFFToRead); - dst_end = info.ptr_lin + info.len_lin; - src = audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, info.ptr_lin, dst_end, src, n_ff_used); - - // Handle wrapped part of FIFO - if (info.len_wrap != 0) + if (info.len_lin != 0) { - dst_end = info.ptr_wrap + info.len_wrap; - audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, info.ptr_wrap, dst_end, src, n_ff_used); + src = &audio->lin_buf_out[cnt_ff*audio->n_channels_per_ff_rx * audio->n_bytes_per_sampe_rx]; + dst_end = info.ptr_lin + info.len_lin; + src = audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, info.ptr_lin, dst_end, src, n_ff_used); + + // Handle wrapped part of FIFO + if (info.len_wrap != 0) + { + dst_end = info.ptr_wrap + info.len_wrap; + audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, info.ptr_wrap, dst_end, src, n_ff_used); + } + tu_fifo_advance_write_pointer(&audio->rx_supp_ff[cnt_ff], info.len_lin + info.len_wrap); } - tu_fifo_advance_write_pointer(&audio->rx_supp_ff[cnt_ff], info.len_lin + info.len_wrap); } // Number of bytes should be a multiple of CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX but checking makes no sense - no way to correct it @@ -976,25 +979,28 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi uint8_t * dst; uint8_t * src_end; - tu_fifo_linear_wr_info info; + tu_fifo_buffer_info_t info; for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) { dst = &audio->lin_buf_in[cnt_ff*audio->n_channels_per_ff_tx*audio->n_bytes_per_sampe_tx]; - info = tu_fifo_get_linear_read_info(&audio->tx_supp_ff[cnt_ff], 0, nBytesPerFFToSend); + tu_fifo_get_read_info(&audio->tx_supp_ff[cnt_ff], &info, nBytesPerFFToSend); - src_end = info.ptr_lin + info.len_lin; - dst = audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, info.ptr_lin, src_end, dst, n_ff_used); - - // Handle wrapped part of FIFO - if (info.len_wrap != 0) + if (info.ptr_lin != 0) { - src_end = info.ptr_wrap + info.len_wrap; - audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, info.ptr_wrap, src_end, dst, n_ff_used); - } + src_end = info.ptr_lin + info.len_lin; + dst = audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, info.ptr_lin, src_end, dst, n_ff_used); - tu_fifo_advance_read_pointer(&audio->tx_supp_ff[cnt_ff], info.len_lin + info.len_wrap); + // Handle wrapped part of FIFO + if (info.len_wrap != 0) + { + src_end = info.ptr_wrap + info.len_wrap; + audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, info.ptr_wrap, src_end, dst, n_ff_used); + } + + tu_fifo_advance_read_pointer(&audio->tx_supp_ff[cnt_ff], info.len_lin + info.len_wrap); + } } return nBytesPerFFToSend * n_ff_used; diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 75dae0906..1c4084882 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -883,7 +883,7 @@ void tu_fifo_advance_read_pointer(tu_fifo_t *f, uint16_t n) /******************************************************************************/ /*! - @brief Get linear read info + @brief Get read info Returns the length and pointer from which bytes can be read in a linear manner. This is of major interest for DMA transmissions. If returned length is zero the @@ -895,24 +895,18 @@ void tu_fifo_advance_read_pointer(tu_fifo_t *f, uint16_t n) wrapped part! @param[in] f Pointer to FIFO - @param[in] offset - Number of ITEMS to ignore before start writing - @param[out] **ptr - Pointer to start writing to - @param[in] n - Number of ITEMS to read from buffer - @return len - Length of linear part IN ITEMS, if zero corresponding pointer ptr is invalid + @param[out] *info + Pointer to struct which holds the desired infos */ /******************************************************************************/ -tu_fifo_linear_wr_info tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, uint16_t n) +void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t n) { // Operate on temporary values in case they change in between uint16_t w = f->wr_idx, r = f->rd_idx; uint16_t cnt = _tu_fifo_count(f, w, r); - // Check overflow and correct if required + // Check overflow and correct if required - may happen in case a DMA wrote too fast if (cnt > f->depth) { _ff_lock(f->mutex_rd); @@ -922,36 +916,40 @@ tu_fifo_linear_wr_info tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offse cnt = f->depth; } - tu_fifo_linear_wr_info info = {0,0,NULL,NULL}; - // Skip beginning of buffer - if (cnt == 0 || offset >= cnt) return info; + if (cnt == 0) + { + info->len_lin = 0; + info->len_wrap = 0; + info->ptr_lin = NULL; + info->ptr_wrap = NULL; + return; + } - // Check if we can read something at and after offset - if too less is available we read what remains - cnt -= offset; if (cnt < n) n = cnt; // Get relative pointers - w = get_relative_pointer(f, w, 0); - r = get_relative_pointer(f, r, offset); + w = get_relative_pointer(f, w,0); + r = get_relative_pointer(f, r,0); // Copy pointer to buffer to start reading from - info.ptr_lin = &f->buffer[r]; - info.ptr_wrap = f->buffer; + info->ptr_lin = &f->buffer[r]; // Check if there is a wrap around necessary if (w > r) { // Non wrapping case - info.len_lin = tu_min16(n, w - r); // Limit to required length - info.len_wrap = 0; + info->len_lin = tu_min16(n, w - r); // Limit to required length + info->len_wrap = 0; + info->ptr_wrap = NULL; } else { - info.len_lin = tu_min16(n, f->depth - r); // Also the case if FIFO was full - info.len_wrap = n-info.len_lin; // n was already limited to what is available + info->len_lin = tu_min16(n, f->depth - r); // Also the case if FIFO was full + info->len_wrap = n-info->len_lin; + info->ptr_wrap = f->buffer; } - return info; + return; } /******************************************************************************/ @@ -967,22 +965,18 @@ tu_fifo_linear_wr_info tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offse time to get a pointer to the wrapped part! @param[in] f Pointer to FIFO - @param[in] offset - Number of ITEMS to ignore before start writing - @param[out] **ptr - Pointer to start writing to + @param[out] *info + Pointer to struct which holds the desired infos @param[in] n Number of ITEMS to write into buffer - @return len - Length of linear part IN ITEMS, if zero corresponding pointer ptr is invalid */ /******************************************************************************/ -tu_fifo_linear_wr_info tu_fifo_get_linear_write_info(tu_fifo_t *f, uint16_t offset, uint16_t n) +void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t n) { uint16_t w = f->wr_idx, r = f->rd_idx; uint16_t free = _tu_fifo_remaining(f, w, r); - tu_fifo_linear_wr_info info = {0,0,NULL,NULL}; + // We need n here because we must enforce the read and write pointers to be not more separated than 2*depth! if (!f->overwritable) { @@ -1002,27 +996,35 @@ tu_fifo_linear_wr_info tu_fifo_get_linear_write_info(tu_fifo_t *f, uint16_t offs } // Check if there is room to write to - if (free == 0 || offset >= free) return info; + if (free == 0) + { + info->len_lin = 0; + info->len_wrap = 0; + info->ptr_lin = NULL; + info->ptr_wrap = NULL; + return; + } // Get relative pointers - w = get_relative_pointer(f, w, offset); - r = get_relative_pointer(f, r, 0); + w = get_relative_pointer(f, w,0); + r = get_relative_pointer(f, r,0); // Copy pointer to buffer to start writing to - info.ptr_lin = &f->buffer[w]; - info.ptr_wrap = f->buffer; // Always start of buffer + info->ptr_lin = &f->buffer[w]; if (w < r) { // Non wrapping case - info.len_lin = tu_min16(n, r-w); // Limit to required length - info.len_wrap = 0; + info->len_lin = tu_min16(n, r-w); // Limit to required length + info->len_wrap = 0; + info->ptr_wrap = NULL; } else { - info.len_lin = tu_min16(n, f->depth - w); // Limit to required length - info.len_wrap = n-info.len_lin; // Remaining length - n already was limited to free or FIFO depth + info->len_lin = tu_min16(n, f->depth - w); // Limit to required length + info->len_wrap = n-info->len_lin; // Remaining length - n already was limited to free or FIFO depth + info->ptr_wrap = f->buffer; // Always start of buffer } - return info; + return; } diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index c23f25723..797a5e728 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -86,7 +86,7 @@ typedef struct uint16_t len_wrap ; ///< wrapped length in item size void * ptr_lin ; ///< linear part start pointer void * ptr_wrap ; ///< wrapped part start pointer -} tu_fifo_linear_wr_info; +} tu_fifo_buffer_info_t; #define TU_FIFO_INIT(_buffer, _depth, _type, _overwritable) \ { \ @@ -144,8 +144,8 @@ void tu_fifo_advance_read_pointer (tu_fifo_t *f, uint16_t n); // tu_fifo_advance_read_pointer()/tu_fifo_advance_write_pointer and conduct a second read/write operation // TODO - update comments -tu_fifo_linear_wr_info tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, uint16_t n); -tu_fifo_linear_wr_info tu_fifo_get_linear_write_info(tu_fifo_t *f, uint16_t offset, uint16_t n); +void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t n); +void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t n); static inline bool tu_fifo_peek(tu_fifo_t* f, void * p_buffer) { From 5f268608d7c15551adddaf20f4b96c0ac1df4633 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 30 Apr 2021 13:39:55 +0200 Subject: [PATCH 07/15] Remove offset feature from fifo.c --- src/common/tusb_fifo.c | 81 +++++++++++++++++++----------------------- src/common/tusb_fifo.h | 6 ++-- 2 files changed, 40 insertions(+), 47 deletions(-) diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 1c4084882..323bb6270 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -348,9 +348,9 @@ static uint16_t backward_pointer(tu_fifo_t* f, uint16_t p, uint16_t offset) } // get relative from absolute pointer -static uint16_t get_relative_pointer(tu_fifo_t* f, uint16_t p, uint16_t offset) +static uint16_t get_relative_pointer(tu_fifo_t* f, uint16_t p) { - return _ff_mod(advance_pointer(f, p, offset), f->depth); + return _ff_mod(p, f->depth); } // Works on local copies of w and r - return only the difference and as such can be used to determine an overflow @@ -396,7 +396,7 @@ static inline void _tu_fifo_correct_read_pointer(tu_fifo_t* f, uint16_t wAbs) // 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_at(tu_fifo_t* f, uint16_t offset, void * p_buffer, uint16_t wAbs, uint16_t rAbs) +static bool _tu_fifo_peek_at(tu_fifo_t* f, void * p_buffer, uint16_t wAbs, uint16_t rAbs) { uint16_t cnt = _tu_fifo_count(f, wAbs, rAbs); @@ -408,9 +408,9 @@ static bool _tu_fifo_peek_at(tu_fifo_t* f, uint16_t offset, void * p_buffer, uin } // Skip beginning of buffer - if (cnt == 0 || offset >= cnt) return false; + if (cnt == 0) return false; - uint16_t rRel = get_relative_pointer(f, rAbs, offset); + uint16_t rRel = get_relative_pointer(f, rAbs); // Peek data _ff_pull(f, p_buffer, rRel); @@ -420,7 +420,7 @@ static bool _tu_fifo_peek_at(tu_fifo_t* f, uint16_t offset, void * p_buffer, uin // 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_at_n(tu_fifo_t* f, uint16_t offset, void * p_buffer, uint16_t n, uint16_t wAbs, uint16_t rAbs, tu_fifo_copy_mode_t copy_mode) +static uint16_t _tu_fifo_peek_at_n(tu_fifo_t* f, void * p_buffer, uint16_t n, uint16_t wAbs, uint16_t rAbs, tu_fifo_copy_mode_t copy_mode) { uint16_t cnt = _tu_fifo_count(f, wAbs, rAbs); @@ -433,13 +433,12 @@ static uint16_t _tu_fifo_peek_at_n(tu_fifo_t* f, uint16_t offset, void * p_buffe } // Skip beginning of buffer - if (cnt == 0 || offset >= cnt) return 0; + if (cnt == 0) return 0; // Check if we can read something at and after offset - if too less is available we read what remains - cnt -= offset; if (cnt < n) n = cnt; - uint16_t rRel = get_relative_pointer(f, rAbs, offset); + uint16_t rRel = get_relative_pointer(f, rAbs); // Peek data _ff_pull_n(f, p_buffer, n, rRel, copy_mode); @@ -479,7 +478,7 @@ static uint16_t _tu_fifo_write_n(tu_fifo_t* f, const void * data, uint16_t n, tu w = r; } - uint16_t wRel = get_relative_pointer(f, w, 0); + uint16_t wRel = get_relative_pointer(f, w); // Write data _ff_push_n(f, buf8, n, wRel, copy_mode); @@ -497,7 +496,7 @@ static uint16_t _tu_fifo_read_n(tu_fifo_t* f, void * buffer, uint16_t n, tu_fifo _ff_lock(f->mutex_rd); // Peek the data - n = _tu_fifo_peek_at_n(f, 0, buffer, n, f->wr_idx, f->rd_idx, copy_mode); // f->rd_idx might get modified in case of an overflow so we can not use a local variable + n = _tu_fifo_peek_at_n(f, buffer, n, f->wr_idx, f->rd_idx, copy_mode); // f->rd_idx might get modified in case of an overflow so we can not use a local variable // Advance read pointer f->rd_idx = advance_pointer(f, f->rd_idx, n); @@ -635,7 +634,7 @@ bool tu_fifo_read(tu_fifo_t* f, void * buffer) _ff_lock(f->mutex_rd); // Peek the data - bool ret = _tu_fifo_peek_at(f, 0, buffer, f->wr_idx, f->rd_idx); // f->rd_idx might get modified in case of an overflow so we can not use a local variable + bool ret = _tu_fifo_peek_at(f, buffer, f->wr_idx, f->rd_idx); // f->rd_idx might get modified in case of an overflow so we can not use a local variable // Advance pointer f->rd_idx = advance_pointer(f, f->rd_idx, ret); @@ -685,10 +684,10 @@ uint16_t tu_fifo_read_n_const_addr_full_words(tu_fifo_t* f, void * buffer, uint1 @returns TRUE if the queue is not empty */ /******************************************************************************/ -bool tu_fifo_peek_at(tu_fifo_t* f, uint16_t offset, void * p_buffer) +bool tu_fifo_peek_at(tu_fifo_t* f, void * p_buffer) { _ff_lock(f->mutex_rd); - bool ret = _tu_fifo_peek_at(f, offset, p_buffer, f->wr_idx, f->rd_idx); + bool ret = _tu_fifo_peek_at(f, p_buffer, f->wr_idx, f->rd_idx); _ff_unlock(f->mutex_rd); return ret; } @@ -700,8 +699,6 @@ bool tu_fifo_peek_at(tu_fifo_t* f, uint16_t offset, void * p_buffer) @param[in] f Pointer to the FIFO buffer to manipulate - @param[in] offset - Position to read from in the FIFO buffer with respect to read pointer @param[in] p_buffer Pointer to the place holder for data read from the buffer @param[in] n @@ -710,10 +707,10 @@ bool tu_fifo_peek_at(tu_fifo_t* f, uint16_t offset, void * p_buffer) @returns Number of bytes written to p_buffer */ /******************************************************************************/ -uint16_t tu_fifo_peek_at_n(tu_fifo_t* f, uint16_t offset, void * p_buffer, uint16_t n) +uint16_t tu_fifo_peek_at_n(tu_fifo_t* f, void * p_buffer, uint16_t n) { _ff_lock(f->mutex_rd); - bool ret = _tu_fifo_peek_at_n(f, offset, p_buffer, n, f->wr_idx, f->rd_idx, TU_FIFO_COPY_INC); + bool ret = _tu_fifo_peek_at_n(f, p_buffer, n, f->wr_idx, f->rd_idx, TU_FIFO_COPY_INC); _ff_unlock(f->mutex_rd); return ret; } @@ -742,7 +739,7 @@ bool tu_fifo_write(tu_fifo_t* f, const void * data) if ( _tu_fifo_full(f, w, f->rd_idx) && !f->overwritable ) return false; - uint16_t wRel = get_relative_pointer(f, w, 0); + uint16_t wRel = get_relative_pointer(f, w); // Write data _ff_push(f, data, wRel); @@ -929,8 +926,8 @@ void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t n if (cnt < n) n = cnt; // Get relative pointers - w = get_relative_pointer(f, w,0); - r = get_relative_pointer(f, r,0); + w = get_relative_pointer(f, w); + r = get_relative_pointer(f, r); // Copy pointer to buffer to start reading from info->ptr_lin = &f->buffer[r]; @@ -976,27 +973,7 @@ void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t uint16_t w = f->wr_idx, r = f->rd_idx; uint16_t free = _tu_fifo_remaining(f, w, r); - // We need n here because we must enforce the read and write pointers to be not more separated than 2*depth! - - if (!f->overwritable) - { - // Not overwritable limit up to full - n = tu_min16(n, free); - } - else if (n >= f->depth) - { - // If overwrite is allowed it must be less than or equal to 2 x buffer length, otherwise the overflow can not be resolved by the read functions - if(n > 2*f->depth) return info; - - n = f->depth; - // We start writing at the read pointer's position since we fill the complete - // buffer and we do not want to modify the read pointer within a write function! - // This would end up in a race condition with read functions! - w = r; - } - - // Check if there is room to write to - if (free == 0) + if (free == 0 || n > 2*f->depth) // If overwrite is allowed it must be less than or equal to 2 x buffer length, otherwise the overflow can not be resolved by the read functions { info->len_lin = 0; info->len_wrap = 0; @@ -1005,9 +982,25 @@ void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t return; } + + // We need n here because we must enforce the read and write pointers to be not more separated than 2*depth! + if (!f->overwritable) + { + // Not overwritable limit up to full + n = tu_min16(n, free); + } + else if (n >= f->depth) + { + n = f->depth; + // We start writing at the read pointer's position since we fill the complete + // buffer and we do not want to modify the read pointer within a write function! + // This would end up in a race condition with read functions! + w = r; + } + // Get relative pointers - w = get_relative_pointer(f, w,0); - r = get_relative_pointer(f, r,0); + w = get_relative_pointer(f, w); + r = get_relative_pointer(f, r); // Copy pointer to buffer to start writing to info->ptr_lin = &f->buffer[w]; diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 797a5e728..fffe87bce 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -123,8 +123,8 @@ bool tu_fifo_read (tu_fifo_t* f, void * p_buffer); uint16_t tu_fifo_read_n (tu_fifo_t* f, void * p_buffer, uint16_t n); uint16_t tu_fifo_read_n_const_addr_full_words (tu_fifo_t* f, void * buffer, uint16_t n); -bool tu_fifo_peek_at (tu_fifo_t* f, uint16_t pos, void * p_buffer); -uint16_t tu_fifo_peek_at_n (tu_fifo_t* f, uint16_t pos, void * p_buffer, uint16_t n); +bool tu_fifo_peek_at (tu_fifo_t* f, void * p_buffer); +uint16_t tu_fifo_peek_at_n (tu_fifo_t* f, void * p_buffer, uint16_t n); uint16_t tu_fifo_count (tu_fifo_t* f); bool tu_fifo_empty (tu_fifo_t* f); @@ -149,7 +149,7 @@ void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t static inline bool tu_fifo_peek(tu_fifo_t* f, void * p_buffer) { - return tu_fifo_peek_at(f, 0, p_buffer); + return tu_fifo_peek_at(f, p_buffer); } static inline uint16_t tu_fifo_depth(tu_fifo_t* f) From de933c45bc627f930e1951ee606aa76784af47cf Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 30 Apr 2021 14:56:14 +0200 Subject: [PATCH 08/15] Remove all remainings with peek_at --- src/class/cdc/cdc_device.c | 4 ++-- src/class/cdc/cdc_device.h | 2 +- src/class/vendor/vendor_device.c | 4 ++-- src/class/vendor/vendor_device.h | 2 +- src/common/tusb_fifo.c | 16 ++++++++-------- src/common/tusb_fifo.h | 9 ++------- test/test/test_fifo.c | 3 --- 7 files changed, 16 insertions(+), 24 deletions(-) diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 0a7691916..f5853fddb 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -146,9 +146,9 @@ uint32_t tud_cdc_n_read(uint8_t itf, void* buffer, uint32_t bufsize) return num_read; } -bool tud_cdc_n_peek(uint8_t itf, int pos, uint8_t* chr) +bool tud_cdc_n_peek(uint8_t itf, uint8_t* chr) { - return tu_fifo_peek_at(&_cdcd_itf[itf].rx_ff, pos, chr); + return tu_fifo_peek(&_cdcd_itf[itf].rx_ff, chr); } void tud_cdc_n_read_flush (uint8_t itf) diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 0885922c6..2566798c5 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -83,7 +83,7 @@ int32_t tud_cdc_n_read_char (uint8_t itf); void tud_cdc_n_read_flush (uint8_t itf); // Get a byte from FIFO at the specified position without removing it -bool tud_cdc_n_peek (uint8_t itf, int pos, uint8_t* u8); +bool tud_cdc_n_peek (uint8_t itf, uint8_t* u8); // Write bytes to TX FIFO, data may remain in the FIFO for a while uint32_t tud_cdc_n_write (uint8_t itf, void const* buffer, uint32_t bufsize); diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index 9b0a3c25f..ef1f5d2fe 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -72,9 +72,9 @@ uint32_t tud_vendor_n_available (uint8_t itf) return tu_fifo_count(&_vendord_itf[itf].rx_ff); } -bool tud_vendor_n_peek(uint8_t itf, int pos, uint8_t* u8) +bool tud_vendor_n_peek(uint8_t itf, uint8_t* u8) { - return tu_fifo_peek_at(&_vendord_itf[itf].rx_ff, pos, u8); + return tu_fifo_peek(&_vendord_itf[itf].rx_ff, u8); } //--------------------------------------------------------------------+ diff --git a/src/class/vendor/vendor_device.h b/src/class/vendor/vendor_device.h index a4235bfce..ffa2e3b70 100644 --- a/src/class/vendor/vendor_device.h +++ b/src/class/vendor/vendor_device.h @@ -45,7 +45,7 @@ bool tud_vendor_n_mounted (uint8_t itf); uint32_t tud_vendor_n_available (uint8_t itf); uint32_t tud_vendor_n_read (uint8_t itf, void* buffer, uint32_t bufsize); -bool tud_vendor_n_peek (uint8_t itf, int pos, uint8_t* u8); +bool tud_vendor_n_peek (uint8_t itf, uint8_t* u8); uint32_t tud_vendor_n_write (uint8_t itf, void const* buffer, uint32_t bufsize); uint32_t tud_vendor_n_write_available (uint8_t itf); diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 323bb6270..92e6bd02c 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -396,7 +396,7 @@ static inline void _tu_fifo_correct_read_pointer(tu_fifo_t* f, uint16_t wAbs) // 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_at(tu_fifo_t* f, void * p_buffer, uint16_t wAbs, uint16_t rAbs) +static bool _tu_fifo_peek(tu_fifo_t* f, void * p_buffer, uint16_t wAbs, uint16_t rAbs) { uint16_t cnt = _tu_fifo_count(f, wAbs, rAbs); @@ -420,7 +420,7 @@ static bool _tu_fifo_peek_at(tu_fifo_t* f, void * p_buffer, uint16_t wAbs, uint1 // 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_at_n(tu_fifo_t* f, void * p_buffer, uint16_t n, uint16_t wAbs, uint16_t rAbs, tu_fifo_copy_mode_t copy_mode) +static uint16_t _tu_fifo_peek_n(tu_fifo_t* f, void * p_buffer, uint16_t n, uint16_t wAbs, uint16_t rAbs, tu_fifo_copy_mode_t copy_mode) { uint16_t cnt = _tu_fifo_count(f, wAbs, rAbs); @@ -496,7 +496,7 @@ static uint16_t _tu_fifo_read_n(tu_fifo_t* f, void * buffer, uint16_t n, tu_fifo _ff_lock(f->mutex_rd); // Peek the data - n = _tu_fifo_peek_at_n(f, buffer, n, f->wr_idx, f->rd_idx, copy_mode); // 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); // f->rd_idx might get modified in case of an overflow so we can not use a local variable // Advance read pointer f->rd_idx = advance_pointer(f, f->rd_idx, n); @@ -634,7 +634,7 @@ bool tu_fifo_read(tu_fifo_t* f, void * buffer) _ff_lock(f->mutex_rd); // Peek the data - bool ret = _tu_fifo_peek_at(f, buffer, f->wr_idx, f->rd_idx); // f->rd_idx might get modified in case of an overflow so we can not use a local variable + bool ret = _tu_fifo_peek(f, buffer, f->wr_idx, f->rd_idx); // f->rd_idx might get modified in case of an overflow so we can not use a local variable // Advance pointer f->rd_idx = advance_pointer(f, f->rd_idx, ret); @@ -684,10 +684,10 @@ uint16_t tu_fifo_read_n_const_addr_full_words(tu_fifo_t* f, void * buffer, uint1 @returns TRUE if the queue is not empty */ /******************************************************************************/ -bool tu_fifo_peek_at(tu_fifo_t* f, void * p_buffer) +bool tu_fifo_peek(tu_fifo_t* f, void * p_buffer) { _ff_lock(f->mutex_rd); - bool ret = _tu_fifo_peek_at(f, p_buffer, f->wr_idx, f->rd_idx); + bool ret = _tu_fifo_peek(f, p_buffer, f->wr_idx, f->rd_idx); _ff_unlock(f->mutex_rd); return ret; } @@ -707,10 +707,10 @@ bool tu_fifo_peek_at(tu_fifo_t* f, void * p_buffer) @returns Number of bytes written to p_buffer */ /******************************************************************************/ -uint16_t tu_fifo_peek_at_n(tu_fifo_t* f, void * p_buffer, uint16_t n) +uint16_t tu_fifo_peek_n(tu_fifo_t* f, void * p_buffer, uint16_t n) { _ff_lock(f->mutex_rd); - bool ret = _tu_fifo_peek_at_n(f, p_buffer, n, f->wr_idx, f->rd_idx, TU_FIFO_COPY_INC); + bool ret = _tu_fifo_peek_n(f, p_buffer, n, f->wr_idx, f->rd_idx, TU_FIFO_COPY_INC); _ff_unlock(f->mutex_rd); return ret; } diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index fffe87bce..36f0d9302 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -123,8 +123,8 @@ bool tu_fifo_read (tu_fifo_t* f, void * p_buffer); uint16_t tu_fifo_read_n (tu_fifo_t* f, void * p_buffer, uint16_t n); uint16_t tu_fifo_read_n_const_addr_full_words (tu_fifo_t* f, void * buffer, uint16_t n); -bool tu_fifo_peek_at (tu_fifo_t* f, void * p_buffer); -uint16_t tu_fifo_peek_at_n (tu_fifo_t* f, void * p_buffer, uint16_t n); +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 (tu_fifo_t* f); bool tu_fifo_empty (tu_fifo_t* f); @@ -147,11 +147,6 @@ void tu_fifo_advance_read_pointer (tu_fifo_t *f, uint16_t n); void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t n); void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t n); -static inline bool tu_fifo_peek(tu_fifo_t* f, void * p_buffer) -{ - return tu_fifo_peek_at(f, p_buffer); -} - static inline uint16_t tu_fifo_depth(tu_fifo_t* f) { return f->depth; diff --git a/test/test/test_fifo.c b/test/test/test_fifo.c index b6c22f569..5ea8de512 100644 --- a/test/test/test_fifo.c +++ b/test/test/test_fifo.c @@ -150,9 +150,6 @@ void test_peek(void) tu_fifo_peek(&ff, &temp); TEST_ASSERT_EQUAL(10, temp); - - tu_fifo_peek_at(&ff, 1, &temp); - TEST_ASSERT_EQUAL(20, temp); } void test_empty(void) From 14e2c004cd9db7d386beb2b91804f8e4dfea55f1 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 30 Apr 2021 15:08:14 +0200 Subject: [PATCH 09/15] Remove variable n in tu_fifo_get_read_info() --- src/class/audio/audio_device.c | 10 ++++++++-- src/common/tusb_fifo.c | 10 ++++------ src/common/tusb_fifo.h | 2 +- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index f19f8f6fe..fc5402834 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -985,13 +985,19 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi { dst = &audio->lin_buf_in[cnt_ff*audio->n_channels_per_ff_tx*audio->n_bytes_per_sampe_tx]; - tu_fifo_get_read_info(&audio->tx_supp_ff[cnt_ff], &info, nBytesPerFFToSend); + tu_fifo_get_read_info(&audio->tx_supp_ff[cnt_ff], &info); - if (info.ptr_lin != 0) + // Limit up to desired length + info.len_lin = tu_min16(nBytesPerFFToSend, info.len_lin); + + if (info.len_lin != 0) { src_end = info.ptr_lin + info.len_lin; dst = audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, info.ptr_lin, src_end, dst, n_ff_used); + // Limit up to desired length + info.len_wrap = tu_min16(nBytesPerFFToSend - info.len_lin, info.len_wrap); + // Handle wrapped part of FIFO if (info.len_wrap != 0) { diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 92e6bd02c..306b68653 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -896,7 +896,7 @@ void tu_fifo_advance_read_pointer(tu_fifo_t *f, uint16_t n) Pointer to struct which holds the desired infos */ /******************************************************************************/ -void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t n) +void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) { // Operate on temporary values in case they change in between uint16_t w = f->wr_idx, r = f->rd_idx; @@ -923,8 +923,6 @@ void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t n return; } - if (cnt < n) n = cnt; - // Get relative pointers w = get_relative_pointer(f, w); r = get_relative_pointer(f, r); @@ -935,14 +933,14 @@ void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t n // Check if there is a wrap around necessary if (w > r) { // Non wrapping case - info->len_lin = tu_min16(n, w - r); // Limit to required length + info->len_lin = cnt; info->len_wrap = 0; info->ptr_wrap = NULL; } else { - info->len_lin = tu_min16(n, f->depth - r); // Also the case if FIFO was full - info->len_wrap = n-info->len_lin; + info->len_lin = f->depth - r; // Also the case if FIFO was full + info->len_wrap = cnt - info->len_lin; info->ptr_wrap = f->buffer; } diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 36f0d9302..c6bcdaec5 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -144,7 +144,7 @@ void tu_fifo_advance_read_pointer (tu_fifo_t *f, uint16_t n); // tu_fifo_advance_read_pointer()/tu_fifo_advance_write_pointer and conduct a second read/write operation // TODO - update comments -void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t n); +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 n); static inline uint16_t tu_fifo_depth(tu_fifo_t* f) From 5f88def9c9fd7e17b8765fda7dceea051a1faa85 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 30 Apr 2021 15:14:27 +0200 Subject: [PATCH 10/15] Comment cleanup --- src/common/tusb_fifo.c | 14 +++++--------- src/common/tusb_fifo.h | 3 --- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 306b68653..c80bb1497 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -884,12 +884,9 @@ void tu_fifo_advance_read_pointer(tu_fifo_t *f, uint16_t n) Returns the length and pointer from which bytes can be read in a linear manner. This is of major interest for DMA transmissions. If returned length is zero the - corresponding pointer is invalid. The returned length is limited to the number - of ITEMS n which the user wants to write into the buffer. - The write pointer does NOT get advanced, use tu_fifo_advance_read_pointer() to - do so! If the length returned is less than n i.e. lenoverwritable) { diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index c6bcdaec5..7bc6b60b9 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -140,9 +140,6 @@ 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 // This functions deliver a pointer to start reading/writing from/to and a valid linear length along which no wrap occurs. -// In case not all of your data is available within one read/write, update the read/write pointer by -// tu_fifo_advance_read_pointer()/tu_fifo_advance_write_pointer and conduct a second read/write operation -// TODO - update comments 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 n); From 54f332fae095c1bc15d631fd3b5ef79f8a707578 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 30 Apr 2021 15:42:27 +0200 Subject: [PATCH 11/15] Fix cdc peeks() --- src/class/cdc/cdc_device.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 2566798c5..614bbf5dc 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -117,7 +117,7 @@ static inline uint32_t tud_cdc_available (void); static inline int32_t tud_cdc_read_char (void); static inline uint32_t tud_cdc_read (void* buffer, uint32_t bufsize); static inline void tud_cdc_read_flush (void); -static inline bool tud_cdc_peek (int pos, uint8_t* u8); +static inline bool tud_cdc_peek (uint8_t* u8); static inline uint32_t tud_cdc_write_char (char ch); static inline uint32_t tud_cdc_write (void const* buffer, uint32_t bufsize); @@ -207,9 +207,9 @@ static inline void tud_cdc_read_flush (void) tud_cdc_n_read_flush(0); } -static inline bool tud_cdc_peek (int pos, uint8_t* u8) +static inline bool tud_cdc_peek (uint8_t* u8) { - return tud_cdc_n_peek(0, pos, u8); + return tud_cdc_n_peek(u8); } static inline uint32_t tud_cdc_write_char (char ch) From 6acfa14fec1805b6f875f4bdbe00360065e72731 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 30 Apr 2021 17:23:34 +0200 Subject: [PATCH 12/15] Fix bug in cdc_peek --- src/class/cdc/cdc_device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 614bbf5dc..986585c5b 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -209,7 +209,7 @@ static inline void tud_cdc_read_flush (void) static inline bool tud_cdc_peek (uint8_t* u8) { - return tud_cdc_n_peek(u8); + return tud_cdc_n_peek(0, u8); } static inline uint32_t tud_cdc_write_char (char ch) From 5add664874f4855491e28c3a869105eb25c5f4d7 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 30 Apr 2021 17:37:14 +0200 Subject: [PATCH 13/15] Remove n from tu_fifo_get_write_info() and fix bug in vendor class --- src/class/audio/audio_device.c | 8 ++++---- src/class/vendor/vendor_device.h | 6 +++--- src/common/tusb_fifo.c | 33 ++++++++------------------------ src/common/tusb_fifo.h | 2 +- 4 files changed, 16 insertions(+), 33 deletions(-) diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index fc5402834..76ebc8aba 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -654,15 +654,17 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, u for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) { - tu_fifo_get_write_info(&audio->rx_supp_ff[cnt_ff], &info, nBytesPerFFToRead); + tu_fifo_get_write_info(&audio->rx_supp_ff[cnt_ff], &info); if (info.len_lin != 0) { + info.len_lin = tu_min16(nBytesPerFFToRead, info.len_lin); src = &audio->lin_buf_out[cnt_ff*audio->n_channels_per_ff_rx * audio->n_bytes_per_sampe_rx]; dst_end = info.ptr_lin + info.len_lin; src = audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, info.ptr_lin, dst_end, src, n_ff_used); // Handle wrapped part of FIFO + info.len_wrap = tu_min16(nBytesPerFFToRead - info.len_lin, info.len_wrap); if (info.len_wrap != 0) { dst_end = info.ptr_wrap + info.len_wrap; @@ -987,11 +989,9 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi tu_fifo_get_read_info(&audio->tx_supp_ff[cnt_ff], &info); - // Limit up to desired length - info.len_lin = tu_min16(nBytesPerFFToSend, info.len_lin); - if (info.len_lin != 0) { + info.len_lin = tu_min16(nBytesPerFFToSend, info.len_lin); // Limit up to desired length src_end = info.ptr_lin + info.len_lin; dst = audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, info.ptr_lin, src_end, dst, n_ff_used); diff --git a/src/class/vendor/vendor_device.h b/src/class/vendor/vendor_device.h index ffa2e3b70..2c3d79a3d 100644 --- a/src/class/vendor/vendor_device.h +++ b/src/class/vendor/vendor_device.h @@ -59,7 +59,7 @@ uint32_t tud_vendor_n_write_str (uint8_t itf, char const* str); static inline bool tud_vendor_mounted (void); static inline uint32_t tud_vendor_available (void); static inline uint32_t tud_vendor_read (void* buffer, uint32_t bufsize); -static inline bool tud_vendor_peek (int pos, uint8_t* u8); +static inline bool tud_vendor_peek (uint8_t* u8); static inline uint32_t tud_vendor_write (void const* buffer, uint32_t bufsize); static inline uint32_t tud_vendor_write_str (char const* str); static inline uint32_t tud_vendor_write_available (void); @@ -95,9 +95,9 @@ static inline uint32_t tud_vendor_read (void* buffer, uint32_t bufsize) return tud_vendor_n_read(0, buffer, bufsize); } -static inline bool tud_vendor_peek (int pos, uint8_t* u8) +static inline bool tud_vendor_peek (uint8_t* u8) { - return tud_vendor_n_peek(0, pos, u8); + return tud_vendor_n_peek(0, u8); } static inline uint32_t tud_vendor_write (void const* buffer, uint32_t bufsize) diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index c80bb1497..a386273f0 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -950,11 +950,9 @@ void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) Returns the length and pointer to which bytes can be written into FIFO in a linear manner. This is of major interest for DMA transmissions not using circular mode. If a returned length is zero the - corresponding pointer is invalid. The returned length is limited to the number of BYTES n which the user - wants to write into the buffer. - The write pointer does NOT get advanced, use tu_fifo_advance_write_pointer() to do so! If the length - returned is less than n i.e. lenwr_idx, r = f->rd_idx; uint16_t free = _tu_fifo_remaining(f, w, r); - if (free == 0 || n > 2*f->depth) // If overwrite is allowed it must be less than or equal to 2 x buffer length, otherwise the overflow can not be resolved by the read functions + if (free == 0) { info->len_lin = 0; info->len_wrap = 0; @@ -977,21 +975,6 @@ void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t return; } - // We need n here because we must enforce the read and write pointers to be not more separated than 2*depth! - if (!f->overwritable) - { - // Not overwritable limit up to full - n = tu_min16(n, free); - } - else if (n >= f->depth) - { - n = f->depth; - // We start writing at the read pointer's position since we fill the complete - // buffer and we do not want to modify the read pointer within a write function! - // This would end up in a race condition with read functions! - w = r; - } - // Get relative pointers w = get_relative_pointer(f, w); r = get_relative_pointer(f, r); @@ -1002,14 +985,14 @@ void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t if (w < r) { // Non wrapping case - info->len_lin = tu_min16(n, r-w); // Limit to required length + info->len_lin = r-w; // Limit to required length info->len_wrap = 0; info->ptr_wrap = NULL; } else { - info->len_lin = tu_min16(n, f->depth - w); // Limit to required length - info->len_wrap = n-info->len_lin; // Remaining length - n already was limited to free or FIFO depth + info->len_lin = f->depth - w; + info->len_wrap = free - info->len_lin; // Remaining length - n already was limited to free or FIFO depth info->ptr_wrap = f->buffer; // Always start of buffer } diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 7bc6b60b9..f8cc282d3 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -142,7 +142,7 @@ void tu_fifo_advance_read_pointer (tu_fifo_t *f, uint16_t n); // This 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_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t n); +void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info); static inline uint16_t tu_fifo_depth(tu_fifo_t* f) { From 18c35bb89e74c3b3455ca7e7cd52a9a3cb1f2d4e Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 2 May 2021 15:01:28 +0700 Subject: [PATCH 14/15] some text fomarting, update unit test to test get buffer info for fifo --- src/common/tusb_fifo.c | 42 +++++----- src/common/tusb_fifo.h | 45 +++++------ test/test/test_fifo.c | 176 +++++++++++++++++++++++++++++++++++------ 3 files changed, 193 insertions(+), 70 deletions(-) diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index a386273f0..81e11eb01 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -57,7 +57,8 @@ static inline void _ff_unlock(tu_fifo_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 + * \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 { @@ -77,7 +78,10 @@ bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_si f->item_size = item_size; f->overwritable = overwritable; - f->max_pointer_idx = 2*depth - 1; // 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) + // 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) + f->max_pointer_idx = 2*depth - 1; f->non_used_index_space = UINT16_MAX - f->max_pointer_idx; f->rd_idx = f->wr_idx = 0; @@ -319,7 +323,8 @@ static void _ff_pull_n(tu_fifo_t* f, void* app_buf, uint16_t n, uint16_t rel, tu static uint16_t advance_pointer(tu_fifo_t* f, uint16_t p, 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 + // 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 if ((p > p + offset) || (p + offset > f->max_pointer_idx)) { p = (p + offset) + f->non_used_index_space; @@ -335,7 +340,8 @@ static uint16_t advance_pointer(tu_fifo_t* f, uint16_t p, uint16_t offset) static uint16_t backward_pointer(tu_fifo_t* f, uint16_t p, 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 + // 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 if ((p < p - offset) || (p - offset > f->max_pointer_idx)) { p = (p - offset) - f->non_used_index_space; @@ -496,7 +502,8 @@ static uint16_t _tu_fifo_read_n(tu_fifo_t* f, void * buffer, uint16_t n, tu_fifo _ff_lock(f->mutex_rd); // Peek the data - n = _tu_fifo_peek_n(f, buffer, n, f->wr_idx, f->rd_idx, copy_mode); // f->rd_idx might get modified in case of an overflow so we can not use a local variable + // 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); // Advance read pointer f->rd_idx = advance_pointer(f, f->rd_idx, n); @@ -634,7 +641,8 @@ bool tu_fifo_read(tu_fifo_t* f, void * buffer) _ff_lock(f->mutex_rd); // Peek the data - bool ret = _tu_fifo_peek(f, buffer, f->wr_idx, f->rd_idx); // f->rd_idx might get modified in case of an overflow so we can not use a local variable + // f->rd_idx might get modified in case of an overflow so we can not use a local variable + bool ret = _tu_fifo_peek(f, buffer, f->wr_idx, f->rd_idx); // Advance pointer f->rd_idx = advance_pointer(f, f->rd_idx, ret); @@ -910,12 +918,12 @@ void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) cnt = f->depth; } - // Skip beginning of buffer + // Check if fifo is empty if (cnt == 0) { - info->len_lin = 0; + info->len_lin = 0; info->len_wrap = 0; - info->ptr_lin = NULL; + info->ptr_lin = NULL; info->ptr_wrap = NULL; return; } @@ -930,18 +938,16 @@ void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) // Check if there is a wrap around necessary if (w > r) { // Non wrapping case - info->len_lin = cnt; + info->len_lin = cnt; info->len_wrap = 0; info->ptr_wrap = NULL; } else { - info->len_lin = f->depth - r; // Also the case if FIFO was full + info->len_lin = f->depth - r; // Also the case if FIFO was full info->len_wrap = cnt - info->len_lin; info->ptr_wrap = f->buffer; } - - return; } /******************************************************************************/ @@ -957,8 +963,6 @@ void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) Pointer to FIFO @param[out] *info Pointer to struct which holds the desired infos - @param[in] n - Number of ITEMS to write into buffer */ /******************************************************************************/ void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) @@ -985,16 +989,14 @@ void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) if (w < r) { // Non wrapping case - info->len_lin = r-w; // Limit to required length + info->len_lin = r-w; info->len_wrap = 0; info->ptr_wrap = NULL; } else { info->len_lin = f->depth - w; - info->len_wrap = free - info->len_lin; // Remaining length - n already was limited to free or FIFO depth - info->ptr_wrap = f->buffer; // Always start of buffer + info->len_wrap = free - info->len_lin; // Remaining length - n already was limited to free or FIFO depth + info->ptr_wrap = f->buffer; // Always start of buffer } - - return; } diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index f8cc282d3..8d73911f0 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -25,10 +25,6 @@ * This file is part of the TinyUSB stack. */ -/** \ingroup Group_Common - * \defgroup group_fifo fifo - * @{ */ - #ifndef _TUSB_FIFO_H_ #define _TUSB_FIFO_H_ @@ -62,16 +58,16 @@ extern "C" { */ typedef struct { - uint8_t* buffer ; ///< buffer pointer - uint16_t depth ; ///< max items - uint16_t item_size ; ///< size of each item - bool overwritable ; + uint8_t* buffer ; ///< buffer pointer + uint16_t depth ; ///< max items + uint16_t item_size ; ///< size of each item + bool overwritable ; - uint16_t non_used_index_space ; ///< required for non-power-of-two buffer length - uint16_t max_pointer_idx ; ///< maximum absolute pointer index + uint16_t non_used_index_space ; ///< required for non-power-of-two buffer length + uint16_t max_pointer_idx ; ///< maximum absolute pointer index - volatile uint16_t wr_idx ; ///< write pointer - volatile uint16_t rd_idx ; ///< read pointer + volatile uint16_t wr_idx ; ///< write pointer + volatile uint16_t rd_idx ; ///< read pointer #if CFG_FIFO_MUTEX tu_fifo_mutex_t mutex_wr; @@ -82,10 +78,10 @@ typedef struct typedef struct { - uint16_t len_lin ; ///< linear length in item size - uint16_t len_wrap ; ///< wrapped length in item size - void * ptr_lin ; ///< linear part start pointer - void * ptr_wrap ; ///< wrapped part start pointer + uint16_t len_lin ; ///< linear length in item size + uint16_t len_wrap ; ///< wrapped length in item size + void * ptr_lin ; ///< linear part start pointer + void * ptr_wrap ; ///< wrapped part start pointer } tu_fifo_buffer_info_t; #define TU_FIFO_INIT(_buffer, _depth, _type, _overwritable) \ @@ -133,21 +129,22 @@ uint16_t tu_fifo_remaining (tu_fifo_t* f); bool tu_fifo_overflowed (tu_fifo_t* f); void tu_fifo_correct_read_pointer (tu_fifo_t* f); +static inline uint16_t tu_fifo_depth(tu_fifo_t* f) +{ + return f->depth; +} + // Pointer modifications intended to be used in combinations with DMAs. // USE WITH CARE - NO SAFTY 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); -// 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 -// This 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); +// 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_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info); -static inline uint16_t tu_fifo_depth(tu_fifo_t* f) -{ - return f->depth; -} #ifdef __cplusplus } diff --git a/test/test/test_fifo.c b/test/test/test_fifo.c index 5ea8de512..f9bfc5f03 100644 --- a/test/test/test_fifo.c +++ b/test/test/test_fifo.c @@ -24,15 +24,19 @@ * This file is part of the TinyUSB stack. */ +#include #include "unity.h" #include "tusb_fifo.h" #define FIFO_SIZE 10 -TU_FIFO_DEF(ff, FIFO_SIZE, uint8_t, false); +TU_FIFO_DEF(tu_ff, FIFO_SIZE, uint8_t, false); +tu_fifo_t* ff = &tu_ff; +tu_fifo_buffer_info_t info; void setUp(void) { - tu_fifo_clear(&ff); + tu_fifo_clear(ff); + memset(&info, 0, sizeof(tu_fifo_buffer_info_t)); } void tearDown(void) @@ -44,12 +48,12 @@ void tearDown(void) //--------------------------------------------------------------------+ void test_normal(void) { - for(uint8_t i=0; i < FIFO_SIZE; i++) tu_fifo_write(&ff, &i); + for(uint8_t i=0; i < FIFO_SIZE; i++) tu_fifo_write(ff, &i); for(uint8_t i=0; i < FIFO_SIZE; i++) { uint8_t c; - tu_fifo_read(&ff, &c); + tu_fifo_read(ff, &c); TEST_ASSERT_EQUAL(i, c); } } @@ -86,30 +90,30 @@ void test_read_n(void) uint8_t data[20]; for(int i=0; i 4 - rd_count = tu_fifo_read_n(&ff, rd, 5); + rd_count = tu_fifo_read_n(ff, rd, 5); TEST_ASSERT_EQUAL( 5, rd_count ); TEST_ASSERT_EQUAL_MEMORY( data, rd, rd_count ); // 0 -> 4 // case 2: Read index + count > depth // write 10, 11, 12 - tu_fifo_write(&ff, data+10); - tu_fifo_write(&ff, data+11); - tu_fifo_write(&ff, data+12); + tu_fifo_write(ff, data+10); + tu_fifo_write(ff, data+11); + tu_fifo_write(ff, data+12); - rd_count = tu_fifo_read_n(&ff, rd, 7); + rd_count = tu_fifo_read_n(ff, rd, 7); TEST_ASSERT_EQUAL( 7, rd_count ); TEST_ASSERT_EQUAL_MEMORY( data+5, rd, rd_count ); // 5 -> 11 // Should only read until empty - TEST_ASSERT_EQUAL( 1, tu_fifo_read_n(&ff, rd, 100) ); + TEST_ASSERT_EQUAL( 1, tu_fifo_read_n(ff, rd, 100) ); } void test_write_n(void) @@ -119,52 +123,172 @@ void test_write_n(void) for(int i=0; i 4 // case 2: wr + count > depth - tu_fifo_write_n(&ff, data+8, 6); // wr = 3, count = 9 + tu_fifo_write_n(ff, data+8, 6); // wr = 3, count = 9 - for(rd_count=0; rd_count<7; rd_count++) tu_fifo_read(&ff, rd+rd_count); // wr = 3, count = 2 + for(rd_count=0; rd_count<7; rd_count++) tu_fifo_read(ff, rd+rd_count); // wr = 3, count = 2 TEST_ASSERT_EQUAL_MEMORY( data+5, rd, rd_count); // 5 -> 11 - TEST_ASSERT_EQUAL(2, tu_fifo_count(&ff)); + TEST_ASSERT_EQUAL(2, tu_fifo_count(ff)); } void test_peek(void) { uint8_t temp; - temp = 10; tu_fifo_write(&ff, &temp); - temp = 20; tu_fifo_write(&ff, &temp); - temp = 30; tu_fifo_write(&ff, &temp); + temp = 10; tu_fifo_write(ff, &temp); + temp = 20; tu_fifo_write(ff, &temp); + temp = 30; tu_fifo_write(ff, &temp); temp = 0; - tu_fifo_peek(&ff, &temp); + tu_fifo_peek(ff, &temp); TEST_ASSERT_EQUAL(10, temp); + + tu_fifo_read(ff, &temp); + tu_fifo_read(ff, &temp); + + tu_fifo_peek(ff, &temp); + TEST_ASSERT_EQUAL(30, temp); +} + +void test_get_read_info_when_no_wrap() +{ + uint8_t ch = 1; + + // write 6 items + for(uint8_t i=0; i < 6; i++) tu_fifo_write(ff, &ch); + + // read 2 items + tu_fifo_read(ff, &ch); + tu_fifo_read(ff, &ch); + + tu_fifo_get_read_info(ff, &info); + + TEST_ASSERT_EQUAL(4, info.len_lin); + TEST_ASSERT_EQUAL(0, info.len_wrap); + + TEST_ASSERT_EQUAL_PTR(ff->buffer+2, info.ptr_lin); + TEST_ASSERT_NULL(info.ptr_wrap); +} + +void test_get_read_info_when_wrapped() +{ + uint8_t ch = 1; + + // make fifo full + for(uint8_t i=0; i < FIFO_SIZE; i++) tu_fifo_write(ff, &ch); + + // read 6 items + for(uint8_t i=0; i < 6; i++) tu_fifo_read(ff, &ch); + + // write 2 items + tu_fifo_write(ff, &ch); + tu_fifo_write(ff, &ch); + + tu_fifo_get_read_info(ff, &info); + + TEST_ASSERT_EQUAL(FIFO_SIZE-6, info.len_lin); + TEST_ASSERT_EQUAL(2, info.len_wrap); + + TEST_ASSERT_EQUAL_PTR(ff->buffer+6, info.ptr_lin); + TEST_ASSERT_EQUAL_PTR(ff->buffer, info.ptr_wrap); +} + +void test_get_write_info_when_no_wrap() +{ + uint8_t ch = 1; + + // write 2 items + tu_fifo_write(ff, &ch); + tu_fifo_write(ff, &ch); + + tu_fifo_get_write_info(ff, &info); + + TEST_ASSERT_EQUAL(FIFO_SIZE-2, info.len_lin); + TEST_ASSERT_EQUAL(0, info.len_wrap); + + TEST_ASSERT_EQUAL_PTR(ff->buffer+2, info .ptr_lin); + // application should check len instead of ptr. + // TEST_ASSERT_NULL(info.ptr_wrap); +} + +void test_get_write_info_when_wrapped() +{ + uint8_t ch = 1; + + // write 6 items + for(uint8_t i=0; i < 6; i++) tu_fifo_write(ff, &ch); + + // read 2 items + tu_fifo_read(ff, &ch); + tu_fifo_read(ff, &ch); + + tu_fifo_get_write_info(ff, &info); + + TEST_ASSERT_EQUAL(FIFO_SIZE-6, info.len_lin); + TEST_ASSERT_EQUAL(2, info.len_wrap); + + TEST_ASSERT_EQUAL_PTR(ff->buffer+6, info .ptr_lin); + TEST_ASSERT_EQUAL_PTR(ff->buffer, info.ptr_wrap); } void test_empty(void) { uint8_t temp; - TEST_ASSERT_TRUE(tu_fifo_empty(&ff)); - tu_fifo_write(&ff, &temp); - TEST_ASSERT_FALSE(tu_fifo_empty(&ff)); + TEST_ASSERT_TRUE(tu_fifo_empty(ff)); + + // read info + tu_fifo_get_read_info(ff, &info); + + TEST_ASSERT_EQUAL(0, info.len_lin); + TEST_ASSERT_EQUAL(0, info.len_wrap); + + TEST_ASSERT_NULL(info.ptr_lin); + TEST_ASSERT_NULL(info.ptr_wrap); + + // write info + tu_fifo_get_write_info(ff, &info); + + TEST_ASSERT_EQUAL(FIFO_SIZE, info.len_lin); + TEST_ASSERT_EQUAL(0, info.len_wrap); + + TEST_ASSERT_EQUAL_PTR(ff->buffer, info .ptr_lin); + // application should check len instead of ptr. + // TEST_ASSERT_NULL(info.ptr_wrap); + + // write 1 then re-check empty + tu_fifo_write(ff, &temp); + TEST_ASSERT_FALSE(tu_fifo_empty(ff)); } void test_full(void) { - TEST_ASSERT_FALSE(tu_fifo_full(&ff)); + TEST_ASSERT_FALSE(tu_fifo_full(ff)); - for(uint8_t i=0; i < FIFO_SIZE; i++) tu_fifo_write(&ff, &i); + for(uint8_t i=0; i < FIFO_SIZE; i++) tu_fifo_write(ff, &i); - TEST_ASSERT_TRUE(tu_fifo_full(&ff)); + TEST_ASSERT_TRUE(tu_fifo_full(ff)); + + // read info + tu_fifo_get_read_info(ff, &info); + + TEST_ASSERT_EQUAL(FIFO_SIZE, info.len_lin); + TEST_ASSERT_EQUAL(0, info.len_wrap); + + TEST_ASSERT_EQUAL_PTR(ff->buffer, info.ptr_lin); + // skip this, application must check len instead of buffer + // TEST_ASSERT_NULL(info.ptr_wrap); + + // write info } From 1e1bcda00338194275eee4aae5280b7b5203f8d0 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 2 May 2021 15:05:47 +0700 Subject: [PATCH 15/15] update changelog for peek api --- docs/changelog.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/changelog.md b/docs/changelog.md index 96c7f6890..436259cee 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -11,6 +11,9 @@ - Rename tud_midi_receive() to tud_midi_packet_read() - Rename tud_midi_send() to tud_midi_packet_write() - New board stm32f072-eval +- Breaking changes + - tud_cdc_peek(), tud_vendor_peek() dropped position parameter. If needed, tu_fifo_get_read_info() can be used to peek + at random offset. ## 0.9.0 - 2021.03.12