add tusbd_cdc_is_busy

enhance cdc serial device demo
refractor fifo.c
This commit is contained in:
hathach 2013-11-08 14:46:48 +07:00
parent 15d3a418bd
commit 7ff0dbb64c
7 changed files with 146 additions and 149 deletions

View File

@ -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

View File

@ -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>

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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