usbd add connected, suspended, remote_wakeup

- remove use of osal_queue_reset
This commit is contained in:
hathach 2019-03-30 02:26:15 +07:00
parent 28610198df
commit 93a853cd5b
8 changed files with 85 additions and 56 deletions

View File

@ -38,7 +38,7 @@
/* Blink pattern /* Blink pattern
* - 250 ms : device not mounted * - 250 ms : device not mounted
* - 1000 ms : device mounted * - 1000 ms : device mounted
* - 2000 ms : device is suspended * - 2500 ms : device is suspended
*/ */
static uint32_t blink_interval_ms = 250; static uint32_t blink_interval_ms = 250;
@ -210,6 +210,18 @@ void tud_umount_cb(void)
blink_interval_ms = 250; blink_interval_ms = 250;
} }
// Invoked when device is suspended
void tud_suspend_cb(bool remote_wakeup_en)
{
(void) remote_wakeup_en;
blink_interval_ms = 2500;
}
void tud_resume_cb(void)
{
blink_interval_ms = 1000;
}
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// BLINKING TASK // BLINKING TASK
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+

View File

@ -48,7 +48,7 @@ typedef enum
DCD_EVENT_SETUP_RECEIVED, DCD_EVENT_SETUP_RECEIVED,
DCD_EVENT_XFER_COMPLETE, DCD_EVENT_XFER_COMPLETE,
USBD_EVT_FUNC_CALL USBD_EVENT_FUNC_CALL
} dcd_eventid_t; } dcd_eventid_t;
typedef struct ATTR_ALIGNED(4) typedef struct ATTR_ALIGNED(4)
@ -67,7 +67,7 @@ typedef struct ATTR_ALIGNED(4)
uint32_t len; uint32_t len;
}xfer_complete; }xfer_complete;
// USBD_EVT_FUNC_CALL // USBD_EVENT_FUNC_CALL
struct { struct {
void (*func) (void*); void (*func) (void*);
void* param; void* param;

View File

@ -40,14 +40,20 @@
// Device Data // Device Data
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
typedef struct { typedef struct {
volatile uint8_t config_num; // 0 is non-configured ~ disconnect volatile uint8_t config_num;
bool remote_wakeup_en;
uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid) struct ATTR_PACKED
uint8_t ep2drv[8][2]; // map endpoint to driver ( 0xff is invalid ) {
volatile uint8_t connected : 1;
volatile uint8_t suspended : 1;
uint8_t remote_wakeup_en : 1;
};
// uint8_t ep_busy_mask[2]; // bit mask for busy endpoint // uint8_t ep_busy_mask[2]; // bit mask for busy endpoint
uint8_t ep_stall_mask[2]; // bit mask for stalled endpoint uint8_t ep_stall_mask[2]; // bit mask for stalled endpoint
uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid)
uint8_t ep2drv[8][2]; // map endpoint to driver ( 0xff is invalid )
}usbd_device_t; }usbd_device_t;
static usbd_device_t _usbd_dev = { 0 }; static usbd_device_t _usbd_dev = { 0 };
@ -246,8 +252,27 @@ void tud_task (void)
if ( !osal_queue_receive(_usbd_q, &event) ) return; if ( !osal_queue_receive(_usbd_q, &event) ) return;
// Skip event if device is not connected except BUS_RESET & UNPLUGGED & FUNC_CALL
if ( !(_usbd_dev.connected || event.event_id == DCD_EVENT_UNPLUGGED ||
event.event_id == DCD_EVENT_BUS_RESET || event.event_id == USBD_EVENT_FUNC_CALL) )
{
return;
}
switch ( event.event_id ) switch ( event.event_id )
{ {
case DCD_EVENT_BUS_RESET:
usbd_reset(event.rhport);
_usbd_dev.connected = 1; // connected after bus reset
break;
case DCD_EVENT_UNPLUGGED:
usbd_reset(event.rhport);
// invoke callback
if (tud_umount_cb) tud_umount_cb();
break;
case DCD_EVENT_SETUP_RECEIVED: case DCD_EVENT_SETUP_RECEIVED:
// Process control request // Process control request
if ( !process_control_request(event.rhport, &event.setup_received) ) if ( !process_control_request(event.rhport, &event.setup_received) )
@ -278,19 +303,15 @@ void tud_task (void)
} }
break; break;
case DCD_EVENT_BUS_RESET: // NOTE: When unplugging device, the D+/D- state are unstable and can accidentally meet the
usbd_reset(event.rhport); // SUSPEND condition ( Idle for 3ms ). Most likely when this happen both suspend and resume
// TODO remove since if task is too slow, we could clear the event of the new attached // are submitted by DCD before the actual UNPLUGGED
osal_queue_reset(_usbd_q); case DCD_EVENT_SUSPEND:
if (tud_suspend_cb) tud_suspend_cb( _usbd_dev.remote_wakeup_en );
break; break;
case DCD_EVENT_UNPLUGGED: case DCD_EVENT_RESUME:
usbd_reset(event.rhport); if (tud_resume_cb) tud_resume_cb();
// TODO remove since if task is too slow, we could clear the event of the new attached
osal_queue_reset(_usbd_q);
// invoke callback
if (tud_umount_cb) tud_umount_cb();
break; break;
case DCD_EVENT_SOF: case DCD_EVENT_SOF:
@ -303,7 +324,7 @@ void tud_task (void)
} }
break; break;
case USBD_EVT_FUNC_CALL: case USBD_EVENT_FUNC_CALL:
if ( event.func_call.func ) event.func_call.func(event.func_call.param); if ( event.func_call.func ) event.func_call.func(event.func_call.param);
break; break;
@ -555,9 +576,8 @@ static void const* get_descriptor(tusb_control_request_t const * p_request, uint
}else }else
{ {
// out of range // out of range
/* The 0xEE index string is a Microsoft USB extension. // The 0xEE index string is a Microsoft USB extension.
* It can be used to tell Windows what driver it should use for the device !!! // It can be used to tell Windows what driver it should use for the device !!!
*/
return NULL; return NULL;
} }
break; break;
@ -587,7 +607,8 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr)
break; break;
case DCD_EVENT_UNPLUGGED: case DCD_EVENT_UNPLUGGED:
_usbd_dev.config_num = 0; // mark disconnected _usbd_dev.connected = 0;
_usbd_dev.config_num = 0;
osal_queue_send(_usbd_q, event, in_isr); osal_queue_send(_usbd_q, event, in_isr);
break; break;
@ -595,9 +616,23 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr)
// nothing to do now // nothing to do now
break; break;
// NOTE: When unplugging device, the D+/D- state are unstable and can accidentally meet the
// SUSPEND condition ( Idle for 3ms ). Most likely when this happen both suspend and resume
// are submitted by DCD before the actual UNPLUGGED
case DCD_EVENT_SUSPEND: case DCD_EVENT_SUSPEND:
if (_usbd_dev.connected ) // skip event if disconnected
{
_usbd_dev.suspended = 1;
osal_queue_send(_usbd_q, event, in_isr);
}
break;
case DCD_EVENT_RESUME: case DCD_EVENT_RESUME:
osal_queue_send(_usbd_q, event, in_isr); if (_usbd_dev.connected ) // skip event if disconnected
{
_usbd_dev.suspended = 0;
osal_queue_send(_usbd_q, event, in_isr);
}
break; break;
case DCD_EVENT_SETUP_RECEIVED: case DCD_EVENT_SETUP_RECEIVED:
@ -606,14 +641,14 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr)
case DCD_EVENT_XFER_COMPLETE: case DCD_EVENT_XFER_COMPLETE:
// skip zero-length control status complete event, should dcd notifies us. // skip zero-length control status complete event, should dcd notifies us.
if ( 0 == tu_edpt_number(event->xfer_complete.ep_addr) && event->xfer_complete.len == 0) break; if ( (0 == tu_edpt_number(event->xfer_complete.ep_addr)) && (event->xfer_complete.len == 0) ) break;
osal_queue_send(_usbd_q, event, in_isr); osal_queue_send(_usbd_q, event, in_isr);
TU_ASSERT(event->xfer_complete.result == XFER_RESULT_SUCCESS,); TU_ASSERT(event->xfer_complete.result == XFER_RESULT_SUCCESS,);
break; break;
// Not an DCD event, just a convenient way to defer ISR function should we need // Not an DCD event, just a convenient way to defer ISR function should we need to
case USBD_EVT_FUNC_CALL: case USBD_EVENT_FUNC_CALL:
osal_queue_send(_usbd_q, event, in_isr); osal_queue_send(_usbd_q, event, in_isr);
break; break;
@ -683,7 +718,7 @@ void usbd_defer_func(osal_task_func_t func, void* param, bool in_isr)
dcd_event_t event = dcd_event_t event =
{ {
.rhport = 0, .rhport = 0,
.event_id = USBD_EVT_FUNC_CALL, .event_id = USBD_EVENT_FUNC_CALL,
}; };
event.func_call.func = func; event.func_call.func = func;

View File

@ -61,7 +61,6 @@ typedef void (*osal_task_func_t)( void * );
* osal_queue_t osal_queue_create(osal_queue_def_t* qdef) * osal_queue_t osal_queue_create(osal_queue_def_t* qdef)
* osal_queue_receive (osal_queue_t const queue_hdl, void *p_data, uint32_t msec, uint32_t *p_error) * osal_queue_receive (osal_queue_t const queue_hdl, void *p_data, uint32_t msec, uint32_t *p_error)
* bool osal_queue_send(osal_queue_t const queue_hdl, void const * data, bool in_isr) * bool osal_queue_send(osal_queue_t const queue_hdl, void const * data, bool in_isr)
* osal_queue_reset()
* *
* Semaphore * Semaphore
* osal_semaphore_def_t, osal_semaphore_t * osal_semaphore_def_t, osal_semaphore_t

View File

@ -125,11 +125,6 @@ static inline bool osal_queue_send(osal_queue_t const queue_hdl, void const * da
return in_isr ? xQueueSendToBackFromISR(queue_hdl, data, NULL) : xQueueSendToBack(queue_hdl, data, OSAL_TIMEOUT_WAIT_FOREVER); return in_isr ? xQueueSendToBackFromISR(queue_hdl, data, NULL) : xQueueSendToBack(queue_hdl, data, OSAL_TIMEOUT_WAIT_FOREVER);
} }
static inline void osal_queue_reset(osal_queue_t const queue_hdl)
{
xQueueReset(queue_hdl);
}
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -161,11 +161,6 @@ static inline bool osal_queue_send(osal_queue_t const qhdl, void const * data, b
return true; return true;
} }
static inline void osal_queue_reset(osal_queue_t const queue_hdl)
{
// TODO implement later
}
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -190,13 +190,6 @@ static inline bool osal_queue_send(osal_queue_t const qhdl, void const * data, b
return success; return success;
} }
static inline void osal_queue_reset(osal_queue_t const qhdl)
{
// tusb_hal_int_disable_all();
tu_fifo_clear(&qhdl->ff);
// tusb_hal_int_enable_all();
}
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -205,13 +205,14 @@ void dcd_set_config (uint8_t rhport, uint8_t config_num)
{ {
(void) rhport; (void) rhport;
(void) config_num; (void) config_num;
// Nothing to do
// Clear current pending // Enable usbevent for suspend and resume detection
// Since the bus signal D+/D- are stable from now on.
// Clear current pending first
NRF_USBD->EVENTCAUSE |= NRF_USBD->EVENTCAUSE; NRF_USBD->EVENTCAUSE |= NRF_USBD->EVENTCAUSE;
NRF_USBD->EVENTS_USBEVENT = 0; NRF_USBD->EVENTS_USBEVENT = 0;
// Enable usb event for suspend and resume
NRF_USBD->INTENSET = USBD_INTEN_USBEVENT_Msk; NRF_USBD->INTENSET = USBD_INTEN_USBEVENT_Msk;
} }
@ -377,19 +378,18 @@ void USBD_IRQHandler(void)
if ( int_status & USBD_INTEN_USBEVENT_Msk ) if ( int_status & USBD_INTEN_USBEVENT_Msk )
{ {
uint32_t const evt_cause = NRF_USBD->EVENTCAUSE; uint32_t const evt_cause = NRF_USBD->EVENTCAUSE & (USBD_EVENTCAUSE_SUSPEND_Msk | USBD_EVENTCAUSE_RESUME_Msk);
NRF_USBD->EVENTCAUSE = evt_cause; // clear interrupt
if ( evt_cause & USBD_EVENTCAUSE_SUSPEND_Msk ) if ( evt_cause & USBD_EVENTCAUSE_SUSPEND_Msk )
{ {
dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true);
} }
if ( evt_cause & USBD_EVENTCAUSE_RESUME_Msk ) if ( evt_cause & USBD_EVENTCAUSE_RESUME_Msk )
{ {
dcd_event_bus_signal(0, DCD_EVENT_RESUME , true); dcd_event_bus_signal(0, DCD_EVENT_RESUME , true);
} }
NRF_USBD->EVENTCAUSE = evt_cause; // clear interrupt
} }
if ( int_status & EDPT_END_ALL_MASK ) if ( int_status & EDPT_END_ALL_MASK )
@ -397,7 +397,7 @@ void USBD_IRQHandler(void)
// DMA complete move data from SRAM -> Endpoint // DMA complete move data from SRAM -> Endpoint
edpt_dma_end(); edpt_dma_end();
} }
// Setup tokens are specific to the Control endpoint. // Setup tokens are specific to the Control endpoint.
if ( int_status & USBD_INTEN_EP0SETUP_Msk ) if ( int_status & USBD_INTEN_EP0SETUP_Msk )
{ {