summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhathach <[email protected]>2018-03-15 13:22:28 +0700
committerhathach <[email protected]>2018-03-15 13:22:28 +0700
commitb0ec6124e014178601d6090bb251757c92c8adbf (patch)
tree70dc145c1568bb6a6a34609edd9a58d7bdf6ff65
parent49a7f8c363c030cb346099a27fdb849aa8f0718d (diff)
nrf52 control transfer work reliably
-rw-r--r--hw/mcu/nordic/nrf52/tusb_port/dcd_nrf52.c62
-rw-r--r--tinyusb/class/cdc/cdc_device.c74
-rw-r--r--tinyusb/device/usbd.c9
-rw-r--r--tinyusb/device/usbd.h7
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)
+ {
+ 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 )
{
- 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;
+ 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;
+ }
+ else if (p_request->wValue == ACTIVE_DTE_NOT_PRESENT)
+ {
+ // terminal disconnected
+ p_cdc->connected = false;
+ }else
+ {
+ // De-active --> disconnected
+ p_cdc->connected = false;
}
- break;
-
- default: return TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT;
+ }
+ 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);