From b0ec6124e014178601d6090bb251757c92c8adbf Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 15 Mar 2018 13:22:28 +0700 Subject: [PATCH] nrf52 control transfer work reliably --- hw/mcu/nordic/nrf52/tusb_port/dcd_nrf52.c | 62 ++++++++++++++++--- tinyusb/class/cdc/cdc_device.c | 74 ++++++++++++----------- tinyusb/device/usbd.c | 9 ++- tinyusb/device/usbd.h | 7 +++ 4 files changed, 102 insertions(+), 50 deletions(-) diff --git a/hw/mcu/nordic/nrf52/tusb_port/dcd_nrf52.c b/hw/mcu/nordic/nrf52/tusb_port/dcd_nrf52.c index e2931efb6..ab64815e2 100644 --- a/hw/mcu/nordic/nrf52/tusb_port/dcd_nrf52.c +++ b/hw/mcu/nordic/nrf52/tusb_port/dcd_nrf52.c @@ -61,6 +61,8 @@ static struct uint16_t xfer_len; uint8_t dir; }control; + + bool dma_running; }_dcd_data; /*------------------------------------------------------------------*/ @@ -138,9 +140,10 @@ static void power_usb_event_handler(nrf_drv_power_usb_evt_t event) nrf_usbd_isosplit_set(NRF_USBD_ISOSPLIT_Half); // Enable interrupt - NRF_USBD->INTENSET = USBD_INTEN_USBRESET_Msk | /*USBD_INTEN_STARTED_Msk |*/ - /*USBD_INTEN_ENDEPIN0_Msk |*/ USBD_INTEN_EP0DATADONE_Msk | USBD_INTEN_ENDEPOUT0_Msk | USBD_INTEN_EP0SETUP_Msk | - USBD_INTEN_USBEVENT_Msk | USBD_INTEN_EPDATA_Msk | USBD_INTEN_ACCESSFAULT_Msk; + NRF_USBD->INTENSET = USBD_INTEN_USBRESET_Msk | USBD_INTEN_USBEVENT_Msk | USBD_INTEN_ACCESSFAULT_Msk | + USBD_INTEN_EP0SETUP_Msk | USBD_INTEN_EP0DATADONE_Msk | + /*USBD_INTEN_ENDEPIN0_Msk |*/ USBD_INTEN_ENDEPOUT0_Msk | + /*USBD_INTEN_STARTED_Msk |*/ USBD_INTEN_EPDATA_Msk ; //USBD_INTEN_SOF_Msk // if (enable_sof || nrf_drv_usbd_errata_104()) @@ -212,28 +215,41 @@ void tusb_dcd_set_config (uint8_t port, uint8_t config_num) static void control_xact_start(void) { + // Each transaction is up to 64 bytes uint8_t xact_len = min16_of(_dcd_data.control.xfer_len, MAX_PACKET_SIZE); if ( _dcd_data.control.dir == TUSB_DIR_OUT ) { + // TODO control out + NRF_USBD->EPOUT[0].PTR = (uint32_t) _dcd_data.control.buffer; + NRF_USBD->EPOUT[0].MAXCNT = xact_len; + NRF_USBD->TASKS_EP0RCVOUT = 1; }else { - // Each transaction is up to 64 bytes NRF_USBD->EPIN[0].PTR = (uint32_t) _dcd_data.control.buffer; NRF_USBD->EPIN[0].MAXCNT = xact_len; - NRF_USBD->TASKS_STARTEPIN[0] = 1; - _dcd_data.control.buffer += xact_len; - _dcd_data.control.xfer_len -= xact_len; + NRF_USBD->TASKS_STARTEPIN[0] = 1; } + + _dcd_data.control.buffer += xact_len; + _dcd_data.control.xfer_len -= xact_len; + } static void control_xact_done(void) { if ( _dcd_data.control.xfer_len > 0 ) { - control_xact_start(); + if ( _dcd_data.control.dir == TUSB_DIR_OUT ) + { + // out control need to wait for END EPOUT event before updating Pointer + NRF_USBD->TASKS_STARTEPOUT[0] = 1; + }else + { + control_xact_start(); + } }else { tusb_dcd_xfer_complete(0, 0, 0, true); @@ -272,6 +288,8 @@ void tusb_dcd_control_stall (uint8_t port) *------------------------------------------------------------------*/ bool tusb_dcd_edpt_open (uint8_t port, tusb_descriptor_endpoint_t const * p_endpoint_desc) { + (void) port; + return true; } @@ -450,6 +468,32 @@ void USBD_IRQHandler(void) if ( int_status & USBD_INTEN_EP0DATADONE_Msk ) { - control_xact_done(); + if ( _dcd_data.control.dir == TUSB_DIR_OUT ) + { + // out control need to wait for END EPOUT (DMA complete) event + NRF_USBD->TASKS_STARTEPOUT[0] = 1; + }else + { + if ( _dcd_data.control.xfer_len > 0 ) + { + control_xact_start(); + }else + { + // Data IN xfer complete + tusb_dcd_xfer_complete(0, 0, 0, true); + } + } + } + + if ( int_status & USBD_INTEN_ENDEPOUT0_Msk) + { + if ( _dcd_data.control.xfer_len > 0 ) + { + control_xact_start(); + }else + { + // Data OUT xfer complete + tusb_dcd_xfer_complete(0, 0, 0, true); + } } } diff --git a/tinyusb/class/cdc/cdc_device.c b/tinyusb/class/cdc/cdc_device.c index 957026d79..837f4e8eb 100644 --- a/tinyusb/class/cdc/cdc_device.c +++ b/tinyusb/class/cdc/cdc_device.c @@ -212,52 +212,54 @@ void cdcd_close(uint8_t port) tusb_error_t cdcd_control_request_subtask(uint8_t port, tusb_control_request_t const * p_request) { + OSAL_SUBTASK_BEGIN + + tusb_error_t err; + //------------- Class Specific Request -------------// if (p_request->bmRequestType_bit.type != TUSB_REQ_TYPE_CLASS) return TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT; - switch(p_request->bRequest) + if (CDC_REQUEST_GET_LINE_CODING == p_request->bRequest) { - case CDC_REQUEST_GET_LINE_CODING: - tusb_dcd_control_xfer(port, (tusb_dir_t) p_request->bmRequestType_bit.direction, - (uint8_t*) &cdcd_line_coding[port], min16_of(sizeof(cdc_line_coding_t), p_request->wLength), false ); - break; + OSAL_SUBTASK_INVOKED( usbd_control_xfer_substak(port, (tusb_dir_t) p_request->bmRequestType_bit.direction, + (uint8_t*) &cdcd_line_coding[port], min16_of(sizeof(cdc_line_coding_t), p_request->wLength)), err ); + } + else if (CDC_REQUEST_SET_LINE_CODING == p_request->bRequest) + { + OSAL_SUBTASK_INVOKED( usbd_control_xfer_substak(port, (tusb_dir_t) p_request->bmRequestType_bit.direction, + (uint8_t*) &cdcd_line_coding[port], min16_of(sizeof(cdc_line_coding_t), p_request->wLength)), err ); + // TODO notify application on xfer completea + } + else if (CDC_REQUEST_SET_CONTROL_LINE_STATE == p_request->bRequest ) + { + enum { + ACTIVE_DTE_PRESENT = 0x0003, + ACTIVE_DTE_NOT_PRESENT = 0x0002 + }; - case CDC_REQUEST_SET_LINE_CODING: - tusb_dcd_control_xfer(port, (tusb_dir_t) p_request->bmRequestType_bit.direction, - (uint8_t*) &cdcd_line_coding[port], min16_of(sizeof(cdc_line_coding_t), p_request->wLength), false ); - // TODO notify application on xfer completea - break; + cdcd_data_t * p_cdc = &cdcd_data[port]; - case CDC_REQUEST_SET_CONTROL_LINE_STATE: // TODO extract DTE present + if (p_request->wValue == ACTIVE_DTE_PRESENT) { - enum { - ACTIVE_DTE_PRESENT = 0x0003, - ACTIVE_DTE_NOT_PRESENT = 0x0002 - }; - - cdcd_data_t * p_cdc = &cdcd_data[port]; - - 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; - } + // terminal connected + p_cdc->connected = true; } - break; - - default: return TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT; + else if (p_request->wValue == ACTIVE_DTE_NOT_PRESENT) + { + // terminal disconnected + p_cdc->connected = false; + }else + { + // De-active --> disconnected + p_cdc->connected = false; + } + } + else + { + SUBTASK_RETURN(TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT); } - return TUSB_ERROR_NONE; + OSAL_SUBTASK_END } tusb_error_t cdcd_xfer_cb(uint8_t port, uint8_t edpt_addr, tusb_event_t event, uint32_t xferred_bytes) diff --git a/tinyusb/device/usbd.c b/tinyusb/device/usbd.c index ed72a2000..f7500b6ed 100644 --- a/tinyusb/device/usbd.c +++ b/tinyusb/device/usbd.c @@ -302,7 +302,7 @@ tusb_error_t usbd_control_xfer_substak(uint8_t port, tusb_dir_t dir, uint8_t * b } // Status opposite direction with Zero Length - tusb_dcd_control_xfer(port, (tusb_dir_t) (1-dir), NULL, 0, true); + usbd_control_status(port, 1-dir); // no need to blocking wait for status to complete @@ -329,7 +329,6 @@ tusb_error_t usbd_control_request_subtask(uint8_t port, tusb_control_request_t c if ( TUSB_ERROR_NONE == error ) { -// tusb_dcd_control_xfer(port, (tusb_dir_t) p_request->bmRequestType_bit.direction, (uint8_t*) p_buffer, length, false); OSAL_SUBTASK_INVOKED ( usbd_control_xfer_substak(port, (tusb_dir_t) p_request->bmRequestType_bit.direction, (uint8_t*) p_buffer, length ), error );; } } @@ -379,12 +378,12 @@ tusb_error_t usbd_control_request_subtask(uint8_t port, tusb_control_request_t c } if(TUSB_ERROR_NONE != error) - { // Response with Protocol Stall if request is not supported + { + // Response with Protocol Stall if request is not supported tusb_dcd_control_stall(port); }else if (p_request->wLength == 0) { - // zero length for non-data - tusb_dcd_control_xfer(port, (tusb_dir_t) p_request->bmRequestType_bit.direction, NULL, 0, false); + usbd_control_status(port, (tusb_dir_t) p_request->bmRequestType_bit.direction); } OSAL_SUBTASK_END diff --git a/tinyusb/device/usbd.h b/tinyusb/device/usbd.h index 8926d225c..cf607f645 100644 --- a/tinyusb/device/usbd.h +++ b/tinyusb/device/usbd.h @@ -130,6 +130,13 @@ void tud_umount_cb(uint8_t port); extern osal_semaphore_t usbd_control_xfer_sem_hdl; +tusb_error_t usbd_control_xfer_substak(uint8_t port, tusb_dir_t dir, uint8_t * buffer, uint16_t length); + +static inline bool usbd_control_status(uint8_t port, tusb_dir_t dir) +{ + tusb_dcd_control_xfer(port , dir, NULL, 0, false); +} + tusb_error_t usbd_init(void); void usbd_task( void* param);