mirror of
https://github.com/hathach/tinyusb.git
synced 2025-04-01 10:20:38 +00:00
add tusbd_cdc_is_busy
enhance cdc serial device demo refractor fifo.c
This commit is contained in:
parent
15d3a418bd
commit
7ff0dbb64c
@ -39,6 +39,9 @@
|
||||
#include "cdcd_app.h"
|
||||
|
||||
#if TUSB_CFG_DEVICE_CDC
|
||||
|
||||
#include "common/fifo.h" // TODO refractor
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// INCLUDE
|
||||
//--------------------------------------------------------------------+
|
||||
@ -54,18 +57,16 @@ OSAL_SEM_DEF(cdcd_semaphore);
|
||||
|
||||
static osal_semaphore_handle_t sem_hdl;
|
||||
|
||||
static uint8_t cdcd_app_recv_buffer[CDCD_APP_BUFFER_SIZE] TUSB_CFG_ATTR_USBRAM;
|
||||
static uint8_t cdcd_app_send_buffer[CDCD_APP_BUFFER_SIZE] TUSB_CFG_ATTR_USBRAM;
|
||||
|
||||
static uint16_t received_bytes; // set by transfer complete callback
|
||||
static uint8_t serial_rx_buffer[CDCD_APP_BUFFER_SIZE] TUSB_CFG_ATTR_USBRAM;
|
||||
static uint8_t serial_tx_buffer[CDCD_APP_BUFFER_SIZE] TUSB_CFG_ATTR_USBRAM;
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// INTERNAL OBJECT & FUNCTION DECLARATION
|
||||
//--------------------------------------------------------------------+
|
||||
FIFO_DEF(fifo_serial, CDCD_APP_BUFFER_SIZE, uint8_t, true);
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// IMPLEMENTATION
|
||||
//--------------------------------------------------------------------+
|
||||
void cdcd_serial_app_init(void)
|
||||
{
|
||||
sem_hdl = osal_semaphore_create( OSAL_SEM_REF(cdcd_semaphore) );
|
||||
@ -78,8 +79,7 @@ void tusbd_cdc_mounted_cb(uint8_t coreid)
|
||||
{
|
||||
osal_semaphore_reset(sem_hdl);
|
||||
|
||||
received_bytes = 0;
|
||||
tusbd_cdc_receive(coreid, cdcd_app_recv_buffer, CDCD_APP_BUFFER_SIZE, true);
|
||||
tusbd_cdc_receive(coreid, serial_rx_buffer, CDCD_APP_BUFFER_SIZE, true);
|
||||
}
|
||||
|
||||
void tusbd_cdc_xfer_isr(uint8_t coreid, tusb_event_t event, cdc_pipeid_t pipe_id, uint32_t xferred_bytes)
|
||||
@ -90,9 +90,12 @@ void tusbd_cdc_xfer_isr(uint8_t coreid, tusb_event_t event, cdc_pipeid_t pipe_id
|
||||
switch(event)
|
||||
{
|
||||
case TUSB_EVENT_XFER_COMPLETE:
|
||||
received_bytes = min16_of(xferred_bytes, CDCD_APP_BUFFER_SIZE); // discard overflow bytes
|
||||
for(uint8_t i=0; i<xferred_bytes; i++)
|
||||
{
|
||||
fifo_write(&fifo_serial, serial_rx_buffer+i);
|
||||
}
|
||||
osal_semaphore_post(sem_hdl); // notify main task
|
||||
break;
|
||||
break;
|
||||
|
||||
case TUSB_EVENT_XFER_ERROR:
|
||||
xferred_bytes = 0; // ignore
|
||||
@ -122,14 +125,23 @@ OSAL_TASK_FUNCTION( cdcd_serial_app_task ) (void* p_task_para)
|
||||
|
||||
if ( tusbd_cdc_is_configured(0) )
|
||||
{
|
||||
if ( received_bytes )
|
||||
{ // echo back
|
||||
memcpy(cdcd_app_send_buffer, cdcd_app_recv_buffer, received_bytes);
|
||||
tusbd_cdc_send(0, cdcd_app_send_buffer, received_bytes, false);
|
||||
received_bytes = 0;
|
||||
// echo back data in the fifo
|
||||
if ( !tusbd_cdc_is_busy(0, CDC_PIPE_DATA_IN) )
|
||||
{
|
||||
uint16_t count=0;
|
||||
while( fifo_read(&fifo_serial, &serial_tx_buffer[count]) )
|
||||
{
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count)
|
||||
{
|
||||
tusbd_cdc_send(0, serial_tx_buffer, count, false);
|
||||
}
|
||||
}
|
||||
|
||||
tusbd_cdc_receive(0, cdcd_app_recv_buffer, CDCD_APP_BUFFER_SIZE, true);
|
||||
// getting next data from host
|
||||
tusbd_cdc_receive(0, serial_rx_buffer, CDCD_APP_BUFFER_SIZE, true);
|
||||
}
|
||||
|
||||
OSAL_TASK_LOOP_END
|
||||
|
@ -448,7 +448,7 @@
|
||||
|
||||
<Group>
|
||||
<GroupName>app</GroupName>
|
||||
<tvExp>0</tvExp>
|
||||
<tvExp>1</tvExp>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
<cbSel>0</cbSel>
|
||||
<RteFlg>0</RteFlg>
|
||||
@ -474,10 +474,10 @@
|
||||
<FileType>1</FileType>
|
||||
<tvExp>0</tvExp>
|
||||
<Focus>0</Focus>
|
||||
<ColumnNumber>0</ColumnNumber>
|
||||
<ColumnNumber>3</ColumnNumber>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
<TopLine>1</TopLine>
|
||||
<CurrentLine>1</CurrentLine>
|
||||
<CurrentLine>2</CurrentLine>
|
||||
<bDave2>0</bDave2>
|
||||
<PathWithFileName>..\src\cdc_serial_app.c</PathWithFileName>
|
||||
<FilenameWithoutPath>cdc_serial_app.c</FilenameWithoutPath>
|
||||
@ -736,7 +736,7 @@
|
||||
|
||||
<Group>
|
||||
<GroupName>tinyusb</GroupName>
|
||||
<tvExp>0</tvExp>
|
||||
<tvExp>1</tvExp>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
<cbSel>0</cbSel>
|
||||
<RteFlg>0</RteFlg>
|
||||
@ -744,7 +744,7 @@
|
||||
<GroupNumber>3</GroupNumber>
|
||||
<FileNumber>18</FileNumber>
|
||||
<FileType>1</FileType>
|
||||
<tvExp>0</tvExp>
|
||||
<tvExp>1</tvExp>
|
||||
<Focus>0</Focus>
|
||||
<ColumnNumber>64</ColumnNumber>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
@ -924,8 +924,8 @@
|
||||
<Focus>0</Focus>
|
||||
<ColumnNumber>0</ColumnNumber>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
<TopLine>0</TopLine>
|
||||
<CurrentLine>0</CurrentLine>
|
||||
<TopLine>54</TopLine>
|
||||
<CurrentLine>62</CurrentLine>
|
||||
<bDave2>0</bDave2>
|
||||
<PathWithFileName>..\..\..\tinyusb\common\fifo.c</PathWithFileName>
|
||||
<FilenameWithoutPath>fifo.c</FilenameWithoutPath>
|
||||
@ -1156,7 +1156,7 @@
|
||||
<Focus>0</Focus>
|
||||
<ColumnNumber>0</ColumnNumber>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
<TopLine>1705</TopLine>
|
||||
<TopLine>1688</TopLine>
|
||||
<CurrentLine>1713</CurrentLine>
|
||||
<bDave2>0</bDave2>
|
||||
<PathWithFileName>..\..\..\vendor\fatfs\ff.c</PathWithFileName>
|
||||
|
@ -92,7 +92,7 @@ void tusbh_cdc_xfer_isr(uint8_t dev_addr, tusb_event_t event, cdc_pipeid_t pipe_
|
||||
break;
|
||||
|
||||
case TUSB_EVENT_XFER_ERROR:
|
||||
xferred_bytes = 0; // ignore
|
||||
received_bytes = 0; // ignore
|
||||
break;
|
||||
|
||||
case TUSB_EVENT_XFER_STALLED:
|
||||
|
@ -74,7 +74,7 @@ static inline bool cdcd_is_configured(uint8_t coreid)
|
||||
return cdcd_data[coreid].interface_number != INTERFACE_INVALID_NUMBER;
|
||||
}
|
||||
|
||||
tusb_error_t cdcd_xfer(uint8_t coreid, cdc_pipeid_t pipeid, void * p_buffer, uint32_t length, bool is_notify)
|
||||
static tusb_error_t cdcd_xfer(uint8_t coreid, cdc_pipeid_t pipeid, void * p_buffer, uint32_t length, bool is_notify)
|
||||
{
|
||||
ASSERT(cdcd_is_configured(coreid), TUSB_ERROR_USBD_INTERFACE_NOT_CONFIGURED);
|
||||
|
||||
@ -88,13 +88,20 @@ tusb_error_t cdcd_xfer(uint8_t coreid, cdc_pipeid_t pipeid, void * p_buffer, ui
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// APPLICATION API
|
||||
// APPLICATION API (Parameters requires validation)
|
||||
//--------------------------------------------------------------------+
|
||||
bool tusbd_cdc_is_configured(uint8_t coreid)
|
||||
{
|
||||
return cdcd_is_configured(coreid);
|
||||
}
|
||||
|
||||
bool tusbd_cdc_is_busy(uint8_t coreid, cdc_pipeid_t pipeid)
|
||||
{
|
||||
ASSERT(cdcd_is_configured(coreid) && (pipeid < CDC_PIPE_ERROR), false);
|
||||
|
||||
return dcd_pipe_is_busy( cdcd_data[coreid].edpt_hdl[pipeid] );
|
||||
}
|
||||
|
||||
tusb_error_t tusbd_cdc_receive(uint8_t coreid, void * p_buffer, uint32_t length, bool is_notify)
|
||||
{
|
||||
return cdcd_xfer(coreid, CDC_PIPE_DATA_OUT, p_buffer, length, is_notify);
|
||||
@ -208,7 +215,7 @@ tusb_error_t cdcd_control_request(uint8_t coreid, tusb_control_request_t const *
|
||||
case CDC_REQUEST_SET_LINE_CODING:
|
||||
dcd_pipe_control_xfer(coreid, p_request->bmRequestType_bit.direction,
|
||||
&cdcd_line_coding[coreid], min16_of(sizeof(cdc_line_coding_t), p_request->wLength) );
|
||||
// TODO notify application
|
||||
// TODO notify application on xfer complete
|
||||
break;
|
||||
|
||||
case CDC_REQUEST_SET_CONTROL_LINE_STATE: // TODO extract DTE present
|
||||
|
@ -58,6 +58,7 @@
|
||||
// APPLICATION API
|
||||
//--------------------------------------------------------------------+
|
||||
bool tusbd_cdc_is_configured(uint8_t coreid);
|
||||
bool tusbd_cdc_is_busy(uint8_t coreid, cdc_pipeid_t pipeid) ATTR_PURE ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
tusb_error_t tusbd_cdc_send(uint8_t coreid, void * p_data, uint32_t length, bool is_notify);
|
||||
tusb_error_t tusbd_cdc_receive(uint8_t coreid, void * p_buffer, uint32_t length, bool is_notify);
|
||||
@ -66,6 +67,7 @@ tusb_error_t tusbd_cdc_receive(uint8_t coreid, void * p_buffer, uint32_t length,
|
||||
void tusbd_cdc_mounted_cb(uint8_t coreid);
|
||||
void tusbd_cdc_unmounted_cb(uint8_t coreid);
|
||||
void tusbd_cdc_xfer_isr(uint8_t coreid, tusb_event_t event, cdc_pipeid_t pipe_id, uint32_t xferred_bytes);
|
||||
void tusbd_cdc_line_coding_changed_cb(uint8_t coreid, cdc_line_coding_t* p_line_coding);
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// USBD-CLASS DRIVER API
|
||||
|
@ -35,68 +35,13 @@
|
||||
This file is part of the tinyusb stack.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include "fifo.h"
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Disables the IRQ specified in the FIFO's 'irq' field
|
||||
to prevent reads/write issues with interrupts
|
||||
static inline void mutex_lock (fifo_t* f) ATTR_ALWAYS_INLINE;
|
||||
static inline void mutex_unlock (fifo_t* f) ATTR_ALWAYS_INLINE;
|
||||
static inline bool is_fifo_initalized(fifo_t* f) ATTR_ALWAYS_INLINE;
|
||||
|
||||
@param[in] f
|
||||
Pointer to the FIFO that should be protected
|
||||
*/
|
||||
/**************************************************************************/
|
||||
static inline void mutex_lock (fifo_t* f)
|
||||
{
|
||||
// if (f->irq > 0)
|
||||
// NVIC_DisableIRQ(f->irq);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Re-enables the IRQ specified in the FIFO's 'irq' field
|
||||
|
||||
@param[in] f
|
||||
Pointer to the FIFO that should be protected
|
||||
*/
|
||||
/**************************************************************************/
|
||||
static inline void mutex_unlock (fifo_t* f)
|
||||
{
|
||||
// if (f->irq > 0)
|
||||
// NVIC_EnableIRQ(f->irq);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Initialises the FIFO buffer
|
||||
|
||||
@param[in] f
|
||||
Pointer to the fifo_t object to intiialize
|
||||
@param[in] buffer
|
||||
Pointer to the buffer's location in memory
|
||||
@param[in] size
|
||||
The buffer size in bytes
|
||||
@param[in] overwritable
|
||||
Set to TRUE is the FIFO is overwritable when the FIFO
|
||||
is full (the first element will be overwritten)
|
||||
@param[in] irq
|
||||
The IRQ number to disable for MUTEX protection.
|
||||
Set the -1 if not required.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
bool fifo_init(fifo_t* f, uint8_t* buffer, uint16_t size, bool overwritable) //, IRQn_Type irq)
|
||||
{
|
||||
ASSERT(size > 0, false);
|
||||
|
||||
f->buf = buffer;
|
||||
f->size = size;
|
||||
f->rd_ptr = f->wr_ptr = f->len = 0;
|
||||
f->overwritable = overwritable;
|
||||
// f->irq = irq;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@ -114,49 +59,26 @@ bool fifo_init(fifo_t* f, uint8_t* buffer, uint16_t size, bool overwritable) //,
|
||||
@returns TRUE if the queue is not empty
|
||||
*/
|
||||
/**************************************************************************/
|
||||
bool fifo_read(fifo_t* f, uint8_t *data)
|
||||
bool fifo_read(fifo_t* f, void * p_buffer)
|
||||
{
|
||||
if (fifo_is_empty(f))
|
||||
if( !is_fifo_initalized(f) || fifo_is_empty(f) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
mutex_lock(f);
|
||||
|
||||
*data = f->buf[f->rd_ptr];
|
||||
f->rd_ptr = (f->rd_ptr + 1) % f->size;
|
||||
f->len--;
|
||||
memcpy(p_buffer,
|
||||
f->buffer + (f->rd_idx * f->item_size),
|
||||
f->item_size);
|
||||
f->rd_idx = (f->rd_idx + 1) % f->depth;
|
||||
f->count--;
|
||||
|
||||
mutex_unlock(f);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Read a byte array from FIFO
|
||||
|
||||
@param[in] f
|
||||
Pointer to the FIFO buffer to manipulate
|
||||
@param[in] rx
|
||||
Pointer to the place holder for data read from the buffer
|
||||
@param[in] maxlen
|
||||
The maximum number of bytes to read from the FIFO
|
||||
|
||||
@returns The actual number of bytes read from the FIFO
|
||||
*/
|
||||
/**************************************************************************/
|
||||
uint16_t fifo_read_n(fifo_t* f, uint8_t* rx, uint16_t maxlen)
|
||||
{
|
||||
uint16_t len = 0;
|
||||
|
||||
while ( len < maxlen && fifo_read(f, rx) )
|
||||
{
|
||||
len++;
|
||||
rx++;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Write one byte into the RX buffer.
|
||||
@ -174,22 +96,27 @@ uint16_t fifo_read_n(fifo_t* f, uint8_t* rx, uint16_t maxlen)
|
||||
FIFO will always return TRUE)
|
||||
*/
|
||||
/**************************************************************************/
|
||||
bool fifo_write(fifo_t* f, uint8_t data)
|
||||
bool fifo_write(fifo_t* f, void const * p_data)
|
||||
{
|
||||
if ( fifo_is_full(f) && f->overwritable == false)
|
||||
return false;
|
||||
if ( !is_fifo_initalized(f) || (fifo_is_full(f) && !f->overwritable) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
mutex_lock(f);
|
||||
|
||||
f->buf[f->wr_ptr] = data;
|
||||
f->wr_ptr = (f->wr_ptr + 1) % f->size;
|
||||
memcpy( f->buffer + (f->wr_idx * f->item_size),
|
||||
p_data,
|
||||
f->item_size);
|
||||
|
||||
f->wr_idx = (f->wr_idx + 1) % f->depth;
|
||||
|
||||
if (fifo_is_full(f))
|
||||
{
|
||||
f->rd_ptr = f->wr_ptr; // keep the full state (rd == wr && len = size)
|
||||
f->rd_idx = f->wr_idx; // keep the full state (rd == wr && len = size)
|
||||
}else
|
||||
{
|
||||
f->len++;
|
||||
f->count++;
|
||||
}
|
||||
|
||||
mutex_unlock(f);
|
||||
@ -209,9 +136,53 @@ void fifo_clear(fifo_t *f)
|
||||
{
|
||||
mutex_lock(f);
|
||||
|
||||
f->rd_ptr = 0;
|
||||
f->wr_ptr = 0;
|
||||
f->len = 0;
|
||||
f->rd_idx = f->wr_idx = f->count = 0;
|
||||
|
||||
mutex_unlock(f);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// HELPER FUNCTIONS
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Disables the IRQ specified in the FIFO's 'irq' field
|
||||
to prevent reads/write issues with interrupts
|
||||
|
||||
@param[in] f
|
||||
Pointer to the FIFO that should be protected
|
||||
*/
|
||||
/**************************************************************************/
|
||||
static inline void mutex_lock (fifo_t* f)
|
||||
{
|
||||
// if (f->irq > 0)
|
||||
// {
|
||||
// #if !defined (_TEST_)
|
||||
// NVIC_DisableIRQ(f->irq);
|
||||
// #endif
|
||||
// }
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Re-enables the IRQ specified in the FIFO's 'irq' field
|
||||
|
||||
@param[in] f
|
||||
Pointer to the FIFO that should be protected
|
||||
*/
|
||||
/**************************************************************************/
|
||||
static inline void mutex_unlock (fifo_t* f)
|
||||
{
|
||||
// if (f->irq > 0)
|
||||
// {
|
||||
// #if !defined (_TEST_)
|
||||
// NVIC_EnableIRQ(f->irq);
|
||||
// #endif
|
||||
// }
|
||||
}
|
||||
|
||||
static inline bool is_fifo_initalized(fifo_t* f)
|
||||
{
|
||||
return !( f->buffer == NULL || f->depth == 0 || f->item_size == 0);
|
||||
}
|
||||
|
@ -36,12 +36,6 @@
|
||||
*/
|
||||
/**************************************************************************/
|
||||
|
||||
/** \file
|
||||
* \brief Error Header
|
||||
*
|
||||
* \note TBD
|
||||
*/
|
||||
|
||||
/** \ingroup Group_Common
|
||||
*
|
||||
* @{
|
||||
@ -59,36 +53,47 @@
|
||||
/** \struct fifo_t
|
||||
* \brief Simple Circular FIFO
|
||||
*/
|
||||
typedef struct _fifo_t
|
||||
typedef struct
|
||||
{
|
||||
uint8_t* buf ; ///< buffer pointer
|
||||
uint16_t size ; ///< buffer size
|
||||
volatile uint16_t len ; ///< bytes in fifo
|
||||
volatile uint16_t wr_ptr ; ///< write pointer
|
||||
volatile uint16_t rd_ptr ; ///< read pointer
|
||||
bool overwritable ; ///< allow overwrite data when full
|
||||
// IRQn_Type irq ; ///< TODO (abstract later) interrupt used to lock fifo
|
||||
uint16_t const depth ; ///< max items
|
||||
uint16_t const item_size ; ///< size of each item
|
||||
volatile uint16_t count ; ///< number of items in queue
|
||||
volatile uint16_t wr_idx ; ///< write pointer
|
||||
volatile uint16_t rd_idx ; ///< read pointer
|
||||
bool overwritable ;
|
||||
uint8_t buffer[] ; ///< buffer pointer
|
||||
// IRQn_Type irq;
|
||||
} fifo_t;
|
||||
|
||||
bool fifo_init(fifo_t* f, uint8_t* buffer, uint16_t size, bool overwritable); //, IRQn_Type irq);
|
||||
bool fifo_write(fifo_t* f, uint8_t data);
|
||||
bool fifo_read(fifo_t* f, uint8_t *data);
|
||||
uint16_t fifo_read_n(fifo_t* f, uint8_t * rx, uint16_t maxlen);
|
||||
#define FIFO_DEF(name, ff_depth, type, is_overwritable) /*, irq_mutex)*/ \
|
||||
fifo_t name = {\
|
||||
.depth = ff_depth,\
|
||||
.item_size = sizeof(type),\
|
||||
.overwritable = is_overwritable,\
|
||||
/*.irq = irq_mutex*/\
|
||||
.buffer = { [ff_depth*sizeof(type) - 1] = 0 },\
|
||||
}
|
||||
|
||||
bool fifo_write(fifo_t* f, void const * p_data);
|
||||
bool fifo_read(fifo_t* f, void * p_buffer);
|
||||
void fifo_clear(fifo_t *f);
|
||||
|
||||
static inline bool fifo_is_empty(fifo_t* f) ATTR_PURE ATTR_ALWAYS_INLINE;
|
||||
static inline bool fifo_is_empty(fifo_t* f)
|
||||
{
|
||||
return (f->len == 0);
|
||||
return (f->count == 0);
|
||||
}
|
||||
|
||||
static inline bool fifo_is_full(fifo_t* f) ATTR_PURE ATTR_ALWAYS_INLINE;
|
||||
static inline bool fifo_is_full(fifo_t* f)
|
||||
{
|
||||
return (f->len == f->size);
|
||||
return (f->count == f->depth);
|
||||
}
|
||||
|
||||
static inline uint16_t fifo_get_length(fifo_t* f) ATTR_PURE ATTR_ALWAYS_INLINE;
|
||||
static inline uint16_t fifo_get_length(fifo_t* f)
|
||||
{
|
||||
return f->len;
|
||||
return f->count;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
Loading…
x
Reference in New Issue
Block a user