From 4ddac8bc88822fc7439b8b2532fe8234d74fee8d Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 8 Mar 2018 14:38:06 +0700 Subject: [PATCH] enhance cdc device API --- .../device_virtual_com/src/cdc_device_app.c | 65 ++----------- .../device_virtual_com/src/cdc_device_app.h | 2 +- examples/device/device_virtual_com/src/main.c | 2 +- hw/bsp/board.c | 2 +- hw/mcu/nxp/lpc43xx/hal/dcd_lpc43xx.c | 8 +- tinyusb/class/cdc/cdc_device.c | 92 ++++++++++++++++--- tinyusb/class/cdc/cdc_device.h | 14 ++- tinyusb/device/dcd.h | 1 + tinyusb/device/usbd.c | 53 ++++++++++- tinyusb/device/usbd.h | 12 ++- 10 files changed, 168 insertions(+), 83 deletions(-) diff --git a/examples/device/device_virtual_com/src/cdc_device_app.c b/examples/device/device_virtual_com/src/cdc_device_app.c index 2ead76f23..866249ac0 100644 --- a/examples/device/device_virtual_com/src/cdc_device_app.c +++ b/examples/device/device_virtual_com/src/cdc_device_app.c @@ -42,40 +42,20 @@ //--------------------------------------------------------------------+ // INCLUDE //--------------------------------------------------------------------+ -enum { SERIAL_BUFFER_SIZE = 64 }; //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -static osal_semaphore_t sem_hdl; //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ -TUSB_CFG_ATTR_USBRAM static uint8_t serial_rx_buffer[SERIAL_BUFFER_SIZE]; -TUSB_CFG_ATTR_USBRAM static uint8_t serial_tx_buffer[SERIAL_BUFFER_SIZE]; - -FIFO_DEF(fifo_serial, SERIAL_BUFFER_SIZE, uint8_t, true); //--------------------------------------------------------------------+ // tinyusb callbacks //--------------------------------------------------------------------+ -void cdc_serial_app_mount(uint8_t coreid) +void tud_cdc_rx_cb(uint8_t coreid) { - osal_semaphore_reset(sem_hdl); - - tud_cdc_receive(coreid, serial_rx_buffer, SERIAL_BUFFER_SIZE, true); -} - -void cdc_serial_app_umount(uint8_t coreid) -{ - -} - -void tud_cdc_rx_cb(uint8_t coreid, uint32_t xferred_bytes) -{ - fifo_write_n(&fifo_serial, serial_rx_buffer, xferred_bytes); - osal_semaphore_post(sem_hdl); // notify main task } //--------------------------------------------------------------------+ @@ -83,50 +63,25 @@ void tud_cdc_rx_cb(uint8_t coreid, uint32_t xferred_bytes) //--------------------------------------------------------------------+ void cdc_serial_app_init(void) { - sem_hdl = osal_semaphore_create(1, 0); - VERIFY(sem_hdl, ); } -tusb_error_t cdc_serial_subtask(void); - -void cdc_serial_app_task(void* param) +void cdc_serial_app_mount(uint8_t coreid) { - (void) param; - - OSAL_TASK_BEGIN - cdc_serial_subtask(); - OSAL_TASK_END } -tusb_error_t cdc_serial_subtask(void) +void cdc_serial_app_umount(uint8_t coreid) { - OSAL_SUBTASK_BEGIN - tusb_error_t error; - (void) error; // suppress compiler's warnings +} - osal_semaphore_wait(sem_hdl, OSAL_TIMEOUT_WAIT_FOREVER, &error); - - if ( tud_mounted(0) ) +void cdc_serial_app_task(void) +{ + if ( tud_mounted(0) && tud_cdc_available(0) ) { - // echo back data in the fifo - if ( !tud_cdc_busy(0, CDC_PIPE_DATA_IN) ) - { - uint16_t count=0; - while( fifo_read(&fifo_serial, &serial_tx_buffer[count]) ) - { - count++; - } + uint8_t buf[64]; - if (count) - { - tud_cdc_send(0, serial_tx_buffer, count, false); - } - } + uint32_t count = tud_cdc_read(0, buf, sizeof(buf)); - // getting more data from host - tud_cdc_receive(0, serial_rx_buffer, SERIAL_BUFFER_SIZE, true); + tud_cdc_write(0, buf, count); } - - OSAL_SUBTASK_END } diff --git a/examples/device/device_virtual_com/src/cdc_device_app.h b/examples/device/device_virtual_com/src/cdc_device_app.h index 24326d379..08c2a1f9e 100644 --- a/examples/device/device_virtual_com/src/cdc_device_app.h +++ b/examples/device/device_virtual_com/src/cdc_device_app.h @@ -54,7 +54,7 @@ #endif void cdc_serial_app_init(void); -void cdc_serial_app_task(void* param); +void cdc_serial_app_task(void); void cdc_serial_app_mount(uint8_t coreid); void cdc_serial_app_umount(uint8_t coreid); diff --git a/examples/device/device_virtual_com/src/main.c b/examples/device/device_virtual_com/src/main.c index 5aa9cf5ff..baf946a56 100644 --- a/examples/device/device_virtual_com/src/main.c +++ b/examples/device/device_virtual_com/src/main.c @@ -74,7 +74,7 @@ int main(void) tusb_task(); led_blinking_task(); - cdc_serial_app_task(NULL); + cdc_serial_app_task(); } return 0; diff --git a/hw/bsp/board.c b/hw/bsp/board.c index c0d7c25b5..575e3859a 100644 --- a/hw/bsp/board.c +++ b/hw/bsp/board.c @@ -37,7 +37,7 @@ /**************************************************************************/ #include "board.h" -#include "app_os_prio.h" +//#include "app_os_prio.h" #if TUSB_CFG_OS == TUSB_OS_NONE diff --git a/hw/mcu/nxp/lpc43xx/hal/dcd_lpc43xx.c b/hw/mcu/nxp/lpc43xx/hal/dcd_lpc43xx.c index 4c5ee53f3..a7ec01d79 100644 --- a/hw/mcu/nxp/lpc43xx/hal/dcd_lpc43xx.c +++ b/hw/mcu/nxp/lpc43xx/hal/dcd_lpc43xx.c @@ -252,7 +252,7 @@ bool hal_dcd_init(uint8_t coreid) lpc_usb->ENDPOINTLISTADDR = (uint32_t) p_dcd->qhd; // Endpoint List Address has to be 2K alignment lpc_usb->USBSTS_D = lpc_usb->USBSTS_D; - lpc_usb->USBINTR_D = INT_MASK_USB | INT_MASK_ERROR | INT_MASK_PORT_CHANGE | INT_MASK_RESET | INT_MASK_SUSPEND; // | INT_MASK_SOF; + lpc_usb->USBINTR_D = INT_MASK_USB | INT_MASK_ERROR | INT_MASK_PORT_CHANGE | INT_MASK_RESET | INT_MASK_SUSPEND /*| INT_MASK_SOF */; lpc_usb->USBCMD_D &= ~0x00FF0000; // Interrupt Threshold Interval = 0 lpc_usb->USBCMD_D |= BIT_(0); // connect @@ -593,7 +593,11 @@ void hal_dcd_isr(uint8_t coreid) } } - if (int_status & INT_MASK_SOF) {} + if (int_status & INT_MASK_SOF) + { +// hal_dcd_bus_event(coreid, USBD_BUS_EVENT_SOF); + } + if (int_status & INT_MASK_NAK) {} if (int_status & INT_MASK_ERROR) ASSERT(false, VOID_RETURN); } diff --git a/tinyusb/class/cdc/cdc_device.c b/tinyusb/class/cdc/cdc_device.c index 56a42032e..4e9a22539 100644 --- a/tinyusb/class/cdc/cdc_device.c +++ b/tinyusb/class/cdc/cdc_device.c @@ -56,9 +56,20 @@ typedef struct { uint8_t interface_number; cdc_acm_capability_t acm_capability; + bool connected; + endpoint_handle_t edpt_hdl[3]; // notification, data in, data out }cdcd_data_t; +// TODO multiple port +TUSB_CFG_ATTR_USBRAM uint8_t _tmp_rx_buf[64]; +TUSB_CFG_ATTR_USBRAM uint8_t _tmp_tx_buf[64]; + +#define CFG_TUD_CDC_BUFSIZE 128 + +FIFO_DEF(_rx_ff, CFG_TUD_CDC_BUFSIZE, uint8_t, true); +FIFO_DEF(_tx_ff, CFG_TUD_CDC_BUFSIZE, uint8_t, true); + //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ @@ -158,13 +169,13 @@ tusb_error_t cdcd_open(uint8_t coreid, tusb_descriptor_interface_t const * p_int for(uint32_t i=0; i<2; i++) { tusb_descriptor_endpoint_t const *p_endpoint = (tusb_descriptor_endpoint_t const *) p_desc; - ASSERT_INT(TUSB_DESC_TYPE_ENDPOINT, p_endpoint->bDescriptorType, TUSB_ERROR_DESCRIPTOR_CORRUPTED); - ASSERT_INT(TUSB_XFER_BULK, p_endpoint->bmAttributes.xfer, TUSB_ERROR_DESCRIPTOR_CORRUPTED); + ASSERT_(TUSB_DESC_TYPE_ENDPOINT == p_endpoint->bDescriptorType, TUSB_ERROR_DESCRIPTOR_CORRUPTED); + ASSERT_(TUSB_XFER_BULK == p_endpoint->bmAttributes.xfer, TUSB_ERROR_DESCRIPTOR_CORRUPTED); endpoint_handle_t * p_edpt_hdl = ( p_endpoint->bEndpointAddress & TUSB_DIR_DEV_TO_HOST_MASK ) ? &p_cdc->edpt_hdl[CDC_PIPE_DATA_IN] : &p_cdc->edpt_hdl[CDC_PIPE_DATA_OUT] ; - VERIFY( hal_dcd_pipe_open(coreid, p_endpoint, p_edpt_hdl), TUSB_ERROR_DCD_OPEN_PIPE_FAILED); + ASSERT_( hal_dcd_pipe_open(coreid, p_endpoint, p_edpt_hdl), TUSB_ERROR_DCD_OPEN_PIPE_FAILED); (*p_length) += p_desc[DESCRIPTOR_OFFSET_LENGTH]; p_desc = descriptor_next( p_desc ); @@ -173,6 +184,10 @@ tusb_error_t cdcd_open(uint8_t coreid, tusb_descriptor_interface_t const * p_int p_cdc->interface_number = p_interface_desc->bInterfaceNumber; + // Prepare for incoming data + hal_dcd_pipe_xfer(p_cdc->edpt_hdl[CDC_PIPE_DATA_OUT], _tmp_rx_buf, sizeof(_tmp_rx_buf), true); + + return TUSB_ERROR_NONE; } @@ -180,6 +195,9 @@ void cdcd_close(uint8_t coreid) { // no need to close opened pipe, dcd bus reset will put controller's endpoints to default state memclr_(&cdcd_data[coreid], sizeof(cdcd_data_t)); + + fifo_clear(&_rx_ff); + fifo_clear(&_tx_ff); } tusb_error_t cdcd_control_request_subtask(uint8_t coreid, tusb_control_request_t const * p_request) @@ -207,16 +225,21 @@ tusb_error_t cdcd_control_request_subtask(uint8_t coreid, tusb_control_request_t ACTIVE_DTE_NOT_PRESENT = 0x0002 }; + cdcd_data_t * p_cdc = &cdcd_data[coreid]; + if (p_request->wValue == ACTIVE_DTE_PRESENT) { // terminal connected + p_cdc->connected = true; } else if (p_request->wValue == ACTIVE_DTE_NOT_PRESENT) { // terminal disconnected + p_cdc->connected = false; }else { // De-active --> disconnected + p_cdc->connected = false; } } break; @@ -231,21 +254,62 @@ tusb_error_t cdcd_xfer_cb(endpoint_handle_t edpt_hdl, tusb_event_t event, uint32 { cdcd_data_t const * p_cdc = &cdcd_data[edpt_hdl.coreid]; - if ( endpointhandle_is_equal(edpt_hdl, p_cdc->edpt_hdl[CDC_PIPE_DATA_OUT]) ) + if ( edpt_equal(edpt_hdl, p_cdc->edpt_hdl[CDC_PIPE_DATA_OUT]) ) { - tud_cdc_rx_cb(edpt_hdl.coreid, xferred_bytes); - } + fifo_write_n(&_rx_ff, _tmp_rx_buf, xferred_bytes); -// for(cdc_pipeid_t pipeid=CDC_PIPE_NOTIFICATION; pipeid < CDC_PIPE_ERROR; pipeid++ ) -// { -// if ( endpointhandle_is_equal(edpt_hdl, p_cdc->edpt_hdl[pipeid]) ) -// { -// tud_cdc_xfer_cb(edpt_hdl.coreid, event, pipeid, xferred_bytes); -// break; -// } -// } + // preparing for next + hal_dcd_pipe_xfer(p_cdc->edpt_hdl[CDC_PIPE_DATA_OUT], _tmp_rx_buf, sizeof(_tmp_rx_buf), true); + + // fire callback + tud_cdc_rx_cb(edpt_hdl.coreid); + } return TUSB_ERROR_NONE; } +void cdcd_sof(uint8_t coreid) +{ + endpoint_handle_t ep = cdcd_data[coreid].edpt_hdl[CDC_PIPE_DATA_IN]; + + if ( !dcd_pipe_is_busy( ep ) ) + { + uint16_t count = fifo_read_n(&_tx_ff, _tmp_tx_buf, sizeof(_tmp_tx_buf)); + + hal_dcd_pipe_xfer(ep, _tmp_tx_buf, count, false); + } +} + +uint32_t tud_cdc_available(uint8_t coreid) +{ + return fifo_count(&_rx_ff); +} + +bool tud_cdc_connected(uint8_t coreid) +{ + return cdcd_data[coreid].connected; +} + +int tud_cdc_read_char(uint8_t coreid) +{ + uint8_t ch; + return fifo_read(&_rx_ff, &ch) ? ch : (-1); +} + +uint32_t tud_cdc_read(uint8_t coreid, void* buffer, uint32_t bufsize) +{ + return fifo_read_n(&_rx_ff, buffer, bufsize); +} + +uint32_t tud_cdc_write_char(uint8_t coreid, char ch) +{ + return fifo_write(&_tx_ff, &ch); +} + +uint32_t tud_cdc_write(uint8_t coreid, void const* buffer, uint32_t bufsize) +{ + return fifo_write_n(&_tx_ff, buffer, bufsize); +} + + #endif diff --git a/tinyusb/class/cdc/cdc_device.h b/tinyusb/class/cdc/cdc_device.h index 44351aad1..d842b8022 100644 --- a/tinyusb/class/cdc/cdc_device.h +++ b/tinyusb/class/cdc/cdc_device.h @@ -95,6 +95,16 @@ tusb_error_t tud_cdc_send(uint8_t coreid, void * p_data, uint32_t length, bool i */ tusb_error_t tud_cdc_receive(uint8_t coreid, void * p_buffer, uint32_t length, bool is_notify); +bool tud_cdc_connected(uint8_t coreid); +uint32_t tud_cdc_available(uint8_t coreid); + +int tud_cdc_read_char(uint8_t coreid); +uint32_t tud_cdc_read(uint8_t coreid, void* buffer, uint32_t bufsize); + +uint32_t tud_cdc_write_char(uint8_t coreid, char ch); +uint32_t tud_cdc_write(uint8_t coreid, void const* buffer, uint32_t bufsize); + + //--------------------------------------------------------------------+ // APPLICATION CALLBACK API //--------------------------------------------------------------------+ @@ -109,7 +119,7 @@ tusb_error_t tud_cdc_receive(uint8_t coreid, void * p_buffer, uint32_t length, b void tud_cdc_xfer_cb(uint8_t coreid, tusb_event_t event, cdc_pipeid_t pipe_id, uint32_t xferred_bytes); //void tud_cdc_line_coding_changed_cb(uint8_t coreid, cdc_line_coding_t* p_line_coding); -void tud_cdc_rx_cb(uint8_t coreid, uint32_t xferred_bytes); +void tud_cdc_rx_cb(uint8_t coreid); //--------------------------------------------------------------------+ // USBD-CLASS DRIVER API @@ -122,6 +132,8 @@ tusb_error_t cdcd_control_request_subtask(uint8_t coreid, tusb_control_request_t tusb_error_t cdcd_xfer_cb(endpoint_handle_t edpt_hdl, tusb_event_t event, uint32_t xferred_bytes); void cdcd_close(uint8_t coreid); +void cdcd_sof(uint8_t coreid); + #endif #ifdef __cplusplus diff --git a/tinyusb/device/dcd.h b/tinyusb/device/dcd.h index 3cf732d23..10704951e 100644 --- a/tinyusb/device/dcd.h +++ b/tinyusb/device/dcd.h @@ -53,6 +53,7 @@ typedef enum { USBD_BUS_EVENT_RESET = 1, USBD_BUS_EVENT_UNPLUGGED, + USBD_BUS_EVENT_SOF, USBD_BUS_EVENT_SUSPENDED, USBD_BUS_EVENT_RESUME }usbd_bus_event_type_t; diff --git a/tinyusb/device/usbd.c b/tinyusb/device/usbd.c index 1ed854cae..5733704db 100644 --- a/tinyusb/device/usbd.c +++ b/tinyusb/device/usbd.c @@ -63,6 +63,8 @@ static usbd_class_driver_t const usbd_class_drivers[] = .open = hidd_open, .control_request_subtask = hidd_control_request_subtask, .xfer_cb = hidd_xfer_cb, +// .routine = NULL, + .sof = NULL, .close = hidd_close }, #endif @@ -74,6 +76,8 @@ static usbd_class_driver_t const usbd_class_drivers[] = .open = mscd_open, .control_request_subtask = mscd_control_request_subtask, .xfer_cb = mscd_xfer_cb, +// .routine = NULL, + .sof = NULL, .close = mscd_close }, #endif @@ -85,6 +89,8 @@ static usbd_class_driver_t const usbd_class_drivers[] = .open = cdcd_open, .control_request_subtask = cdcd_control_request_subtask, .xfer_cb = cdcd_xfer_cb, +// .routine = NULL, + .sof = cdcd_sof, .close = cdcd_close }, #endif @@ -117,7 +123,8 @@ enum { USBD_TASK_QUEUE_DEPTH = 16 }; typedef enum { USBD_EVENTID_SETUP_RECEIVED = 1, - USBD_EVENTID_XFER_DONE + USBD_EVENTID_XFER_DONE, + USBD_EVENTID_SOF }usbd_eventid_t; typedef struct ATTR_ALIGNED(4) @@ -128,7 +135,7 @@ typedef struct ATTR_ALIGNED(4) uint8_t reserved; union { - tusb_control_request_t setup_received; // USBD_EVENTID_SETUP_RECEIVED + tusb_control_request_t setup_received; struct { // USBD_EVENTID_XFER_DONE endpoint_handle_t edpt_hdl; @@ -213,8 +220,27 @@ static tusb_error_t usbd_body_subtask(void) error = TUSB_ERROR_NONE; memclr_(&event, sizeof(usbd_task_event_t)); + +#if 1 osal_queue_receive(usbd_queue_hdl, &event, OSAL_TIMEOUT_WAIT_FOREVER, &error); SUBTASK_ASSERT_STATUS(error); +#else + enum { ROUTINE_INTERVAL_MS = 10 }; + osal_queue_receive(usbd_queue_hdl, &event, ROUTINE_INTERVAL_MS, &error); + if ( error != TUSB_ERROR_NONE ) + { + // time out, run class routine then + if ( error == TUSB_ERROR_OSAL_TIMEOUT) + { + for (uint8_t class_code = TUSB_CLASS_AUDIO; class_code < USBD_CLASS_DRIVER_COUNT; class_code++) + { + if ( usbd_class_drivers[class_code].routine ) usbd_class_drivers[class_code].routine(); + } + } + + SUBTASK_RETURN(error); + } +#endif if ( USBD_EVENTID_SETUP_RECEIVED == event.event_id ) { @@ -229,7 +255,17 @@ static tusb_error_t usbd_body_subtask(void) usbd_class_drivers[class_code].xfer_cb( event.xfer_done.edpt_hdl, (tusb_event_t) event.sub_event_id, event.xfer_done.xferred_byte); } } - }else + }else if (USBD_EVENTID_SOF == event.event_id) + { + for (uint8_t class_code = TUSB_CLASS_AUDIO; class_code < USBD_CLASS_DRIVER_COUNT; class_code++) + { + if ( usbd_class_drivers[class_code].sof ) + { + usbd_class_drivers[class_code].sof( event.coreid ); + } + } + } + else { SUBTASK_ASSERT(false); } @@ -429,6 +465,17 @@ void hal_dcd_bus_event(uint8_t coreid, usbd_bus_event_type_t bus_event) tud_umount_cb(coreid); break; + case USBD_BUS_EVENT_SOF: + { + usbd_task_event_t task_event = + { + .coreid = coreid, + .event_id = USBD_EVENTID_SOF, + }; + osal_queue_send(usbd_queue_hdl, &task_event); + } + break; + case USBD_BUS_EVENT_UNPLUGGED : break; case USBD_BUS_EVENT_SUSPENDED: diff --git a/tinyusb/device/usbd.h b/tinyusb/device/usbd.h index 28923dfae..df6006c63 100644 --- a/tinyusb/device/usbd.h +++ b/tinyusb/device/usbd.h @@ -77,11 +77,13 @@ typedef struct { extern tusbd_descriptor_pointer_t tusbd_descriptor_pointers; typedef struct { - void (* const init) (void); - tusb_error_t (* const open)(uint8_t, tusb_descriptor_interface_t const *, uint16_t*); - tusb_error_t (* const control_request_subtask) (uint8_t, tusb_control_request_t const *); - tusb_error_t (* const xfer_cb) (endpoint_handle_t, tusb_event_t, uint32_t); - void (* const close) (uint8_t); + void (* init) (void); + tusb_error_t (* open)(uint8_t, tusb_descriptor_interface_t const *, uint16_t*); + tusb_error_t (* control_request_subtask) (uint8_t coreid, tusb_control_request_t const *); + tusb_error_t (* xfer_cb) (endpoint_handle_t, tusb_event_t, uint32_t); +// void (* routine)(void); + void (* sof)(uint8_t coreid); + void (* close) (uint8_t); } usbd_class_driver_t; //--------------------------------------------------------------------+