summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHa Thach <[email protected]>2021-05-02 15:29:38 +0700
committerGitHub <[email protected]>2021-05-02 15:29:38 +0700
commit42a1d2f3b9d40b57a7ef8364c138d8274f1a0a8d (patch)
treea7ad018e09c53335a69dbffa7666a13837a84102 /src
parent30b7988efa7b2468a51e8f5619f1108cef3a1421 (diff)
parent1e1bcda00338194275eee4aae5280b7b5203f8d0 (diff)
Merge pull request #804 from hathach/audio_make_dma_ready
Implement functions to allow for DMA usage in audio driver.
Diffstat (limited to 'src')
-rw-r--r--src/class/audio/audio_device.c105
-rw-r--r--src/class/audio/audio_device.h28
-rw-r--r--src/class/cdc/cdc_device.c4
-rw-r--r--src/class/cdc/cdc_device.h8
-rw-r--r--src/class/vendor/vendor_device.c4
-rw-r--r--src/class/vendor/vendor_device.h8
-rw-r--r--src/common/tusb_fifo.c189
-rw-r--r--src/common/tusb_fifo.h57
-rw-r--r--src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c4
9 files changed, 220 insertions, 187 deletions
diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c
index 0a60d9ee5..76ebc8aba 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
@@ -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,31 +647,30 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, u
uint8_t cnt_ff;
// Decode
- void * dst;
uint8_t * src;
uint8_t * dst_end;
- uint16_t len;
+
+ 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];
-
- 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);
-
- dst_end = dst + len;
-
- src = audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, dst, dst_end, src, n_ff_used);
+ tu_fifo_get_write_info(&audio->rx_supp_ff[cnt_ff], &info);
- // Handle wrapped part of FIFO
- if (len < nBytesPerFFToRead)
+ if (info.len_lin != 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);
+ 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);
- dst_end = dst + len;
-
- audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, dst, 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;
+ 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);
}
}
@@ -699,9 +710,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 +737,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 +776,7 @@ uint16_t tud_audio_int_ctr_n_write(uint8_t func_id, uint8_t const* buffer, uint1
return true;
}
+
#endif
@@ -952,31 +978,34 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi
nBytesPerFFToSend = (nBytesPerFFToSend / nBytesToCopy) * nBytesToCopy;
// Encode
- void * src;
uint8_t * dst;
uint8_t * src_end;
- uint16_t len;
+
+ 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];
- 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);
-
- src_end = src + len;
-
- dst = audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, src, src_end, dst, n_ff_used);
+ tu_fifo_get_read_info(&audio->tx_supp_ff[cnt_ff], &info);
- // Handle wrapped part of FIFO
- if (len < nBytesPerFFToSend)
+ if (info.len_lin != 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);
+ 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);
- src_end = src + len;
+ // 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)
+ {
+ src_end = info.ptr_wrap + info.len_wrap;
+ audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, info.ptr_wrap, src_end, dst, n_ff_used);
+ }
- audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, src, src_end, dst, n_ff_used);
+ tu_fifo_advance_read_pointer(&audio->tx_supp_ff[cnt_ff], info.len_lin + info.len_wrap);
}
}
diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h
index c070e48c2..b8e6ef9c0 100644
--- a/src/class/audio/audio_device.h
+++ b/src/class/audio/audio_device.h
@@ -364,23 +364,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 +403,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 +418,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 +522,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 +546,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 +567,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 +591,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/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..986585c5b 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);
@@ -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(0, u8);
}
static inline uint32_t tud_cdc_write_char (char ch)
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..2c3d79a3d 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);
@@ -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 098d54801..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;
@@ -348,9 +354,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 +402,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(tu_fifo_t* f, void * p_buffer, uint16_t wAbs, uint16_t rAbs)
{
uint16_t cnt = _tu_fifo_count(f, wAbs, rAbs);
@@ -408,9 +414,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 +426,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_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 +439,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 +484,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 +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_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
+ // 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);
@@ -635,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_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
+ // 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);
@@ -685,10 +692,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(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(f, p_buffer, f->wr_idx, f->rd_idx);
_ff_unlock(f->mutex_rd);
return ret;
}
@@ -700,8 +707,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 +715,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_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_n(f, p_buffer, n, f->wr_idx, f->rd_idx, TU_FIFO_COPY_INC);
_ff_unlock(f->mutex_rd);
return ret;
}
@@ -742,7 +747,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);
@@ -883,36 +888,27 @@ 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
- 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. len<n, then a wrap occurs
- and you need to execute this function a second time to get a pointer to the
- wrapped part!
+ corresponding pointer is invalid.
+ The read pointer does NOT get advanced, use tu_fifo_advance_read_pointer() to
+ do so!
@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
*/
/******************************************************************************/
-uint16_t tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, void **ptr, 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;
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,104 +918,85 @@ uint16_t tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, void **ptr,
cnt = f->depth;
}
- // Skip beginning of buffer
- if (cnt == 0 || offset >= cnt) 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;
+ // Check if fifo is empty
+ if (cnt == 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, 0);
- r = get_relative_pointer(f, r, offset);
+ w = get_relative_pointer(f, w);
+ r = get_relative_pointer(f, r);
- // Check if there is a wrap around necessary
- uint16_t len;
+ // Copy pointer to buffer to start reading from
+ info->ptr_lin = &f->buffer[r];
+ // Check if there is a wrap around necessary
if (w > r) {
- len = w - r;
+ // Non wrapping case
+ info->len_lin = cnt;
+ info->len_wrap = 0;
+ info->ptr_wrap = NULL;
}
else
{
- len = 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;
}
-
- // Limit to required length
- len = tu_min16(n, len);
-
- // Copy pointer to buffer to start reading from
- *ptr = &f->buffer[r];
-
- return len;
}
/******************************************************************************/
/*!
@brief Get linear write info
- Returns the length and pointer from which bytes can be written into buffer array in a linear manner.
- This is of major interest for DMA transmissions not using circular mode. If 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. len<n, then a wrap occurs and you need to execute this function a second
- time to get a pointer to the wrapped part!
+ 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 lengths summed up are the currently free space in the FIFO.
+ The write pointer does NOT get advanced, use tu_fifo_advance_write_pointer() to do so!
+ TAKE CARE TO NOT OVERFLOW THE BUFFER MORE THAN TWO TIMES THE FIFO DEPTH - IT CAN NOT RECOVERE OTHERWISE!
@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 write into 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
*/
/******************************************************************************/
-uint16_t tu_fifo_get_linear_write_info(tu_fifo_t *f, uint16_t offset, void **ptr, uint16_t n)
+void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info)
{
uint16_t w = f->wr_idx, r = f->rd_idx;
uint16_t free = _tu_fifo_remaining(f, w, r);
- if (!f->overwritable)
+ if (free == 0)
{
- // 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
- TU_VERIFY(n <= 2*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;
+ info->len_lin = 0;
+ info->len_wrap = 0;
+ info->ptr_lin = NULL;
+ info->ptr_wrap = NULL;
+ return;
}
- // Check if there is room to write to
- if (free == 0 || offset >= free) return 0;
-
// Get relative pointers
- w = get_relative_pointer(f, w, offset);
- r = get_relative_pointer(f, r, 0);
- uint16_t len;
+ 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];
if (w < r)
{
- len = r-w;
+ // Non wrapping case
+ info->len_lin = r-w;
+ info->len_wrap = 0;
+ info->ptr_wrap = NULL;
}
else
{
- len = f->depth - w;
+ 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
}
-
- // 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..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;
@@ -80,6 +76,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_buffer_info_t;
+
#define TU_FIFO_INIT(_buffer, _depth, _type, _overwritable) \
{ \
.buffer = _buffer, \
@@ -115,8 +119,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 (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);
@@ -125,27 +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.
-// 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);
-
-static inline bool tu_fifo_peek(tu_fifo_t* f, void * p_buffer)
-{
- return tu_fifo_peek_at(f, 0, p_buffer);
-}
+// 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/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);