mirror of
https://github.com/hathach/tinyusb.git
synced 2025-01-31 05:52:55 +08:00
nrf52 control transfer work reliably
This commit is contained in:
parent
49a7f8c363
commit
b0ec6124e0
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user