summaryrefslogtreecommitdiff
path: root/src/portable
diff options
context:
space:
mode:
authorWini-Buh <[email protected]>2021-06-22 23:21:01 +0200
committerWini-Buh <[email protected]>2021-06-22 23:21:01 +0200
commitc5f6b57755052284e2fec8aa79b93272e757b297 (patch)
treecec76cd5772eccd703a633d1ff2d71fc64a5f1dd /src/portable
parent60d8ecbfe617b0f398f90c3fede9a9488f4da407 (diff)
parent5a4fc1151a7e62a291a90836165942737a1a2d6f (diff)
Merge remote-tracking branch 'upstream/master' into CCRX_Port
Diffstat (limited to 'src/portable')
-rw-r--r--src/portable/microchip/samd/dcd_samd.c4
-rw-r--r--src/portable/nordic/nrf5x/dcd_nrf5x.c59
2 files changed, 43 insertions, 20 deletions
diff --git a/src/portable/microchip/samd/dcd_samd.c b/src/portable/microchip/samd/dcd_samd.c
index 13e56453d..577bd0e05 100644
--- a/src/portable/microchip/samd/dcd_samd.c
+++ b/src/portable/microchip/samd/dcd_samd.c
@@ -29,7 +29,7 @@
#if TUSB_OPT_DEVICE_ENABLED && \
(CFG_TUSB_MCU == OPT_MCU_SAMD11 || CFG_TUSB_MCU == OPT_MCU_SAMD21 || \
CFG_TUSB_MCU == OPT_MCU_SAMD51 || CFG_TUSB_MCU == OPT_MCU_SAME5X || \
- CFG_TUSB_MCU == OPT_MCU_SAML22)
+ CFG_TUSB_MCU == OPT_MCU_SAML22 || CFG_TUSB_MCU == OPT_MCU_SAML21)
#include "sam.h"
#include "device/dcd.h"
@@ -125,7 +125,7 @@ void dcd_int_disable(uint8_t rhport)
}
#elif CFG_TUSB_MCU == OPT_MCU_SAMD11 || CFG_TUSB_MCU == OPT_MCU_SAMD21 || \
- CFG_TUSB_MCU == OPT_MCU_SAML22
+ CFG_TUSB_MCU == OPT_MCU_SAML22 || CFG_TUSB_MCU == OPT_MCU_SAML21
void dcd_int_enable(uint8_t rhport)
{
diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c
index 977ec6cdb..b3b2dec2d 100644
--- a/src/portable/nordic/nrf5x/dcd_nrf5x.c
+++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c
@@ -108,13 +108,21 @@ static inline uint32_t NVIC_GetEnableIRQ(IRQn_Type IRQn)
}
#endif
+// check if we are in ISR
+TU_ATTR_ALWAYS_INLINE static inline bool is_in_isr(void)
+{
+ return (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) ? true : false;
+}
+
// helper to start DMA
+// TODO use Cortex M4 LDREX and STREX command (atomic) to have better mutex access to EasyDMA
+// since current implementation does not 100% guarded against race condition
static void edpt_dma_start(volatile uint32_t* reg_startep)
{
// Only one dma can be active
if ( _dcd.dma_pending )
{
- if (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk)
+ if (is_in_isr())
{
// Called within ISR, use usbd task to defer later
usbd_defer_func( (osal_task_func_t) edpt_dma_start, (void*) reg_startep, true );
@@ -159,6 +167,17 @@ static void edpt_dma_end(void)
_dcd.dma_pending = 0;
}
+// helper to set TASKS_EP0STATUS / TASKS_EP0RCVOUT since they also need EasyDMA
+// However TASKS_EP0STATUS doesn't trigger any DMA transfer and got ENDED event subsequently
+// Therefore dma_running state will be corrected right away
+void start_ep0_task(volatile uint32_t* reg_task)
+{
+ edpt_dma_start(reg_task);
+
+ // correct the dma_running++ in dma start
+ if (_dcd.dma_pending) _dcd.dma_pending--;
+}
+
// helper getting td
static inline xfer_td_t* get_td(uint8_t epnum, uint8_t dir)
{
@@ -407,21 +426,18 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t
if ( control_status )
{
- // Status Phase also requires Easy DMA has to be available as well !!!!
- // However TASKS_EP0STATUS doesn't trigger any DMA transfer and got ENDED event subsequently
- // Therefore dma_running state will be corrected right away
- edpt_dma_start(&NRF_USBD->TASKS_EP0STATUS);
- if (_dcd.dma_pending) _dcd.dma_pending--; // correct the dma_running++ in dma start
+ // Status Phase also requires EasyDMA has to be available as well !!!!
+ start_ep0_task(&NRF_USBD->TASKS_EP0STATUS);
// The nRF doesn't interrupt on status transmit so we queue up a success response.
- dcd_event_xfer_complete(0, ep_addr, 0, XFER_RESULT_SUCCESS, false);
+ dcd_event_xfer_complete(0, ep_addr, 0, XFER_RESULT_SUCCESS, is_in_isr());
}
else if ( dir == TUSB_DIR_OUT )
{
if ( epnum == 0 )
{
- // Accept next Control Out packet
- NRF_USBD->TASKS_EP0RCVOUT = 1;
+ // Accept next Control Out packet. TASKS_EP0RCVOUT also require EasyDMA
+ start_ep0_task(&NRF_USBD->TASKS_EP0RCVOUT);
}else
{
if ( xfer->data_received )
@@ -581,12 +597,6 @@ void dcd_int_handler(uint8_t rhport)
}
}
- if ( int_status & EDPT_END_ALL_MASK )
- {
- // DMA complete move data from SRAM -> Endpoint
- edpt_dma_end();
- }
-
// Setup tokens are specific to the Control endpoint.
if ( int_status & USBD_INTEN_EP0SETUP_Msk )
{
@@ -607,6 +617,12 @@ void dcd_int_handler(uint8_t rhport)
}
}
+ if ( int_status & EDPT_END_ALL_MASK )
+ {
+ // DMA complete move data from SRAM -> Endpoint
+ edpt_dma_end();
+ }
+
//--------------------------------------------------------------------+
/* Control/Bulk/Interrupt (CBI) Transfer
*
@@ -655,8 +671,15 @@ void dcd_int_handler(uint8_t rhport)
{
if ( epnum == 0 )
{
- // Accept next Control Out packet
- NRF_USBD->TASKS_EP0RCVOUT = 1;
+ // Accept next Control Out packet. TASKS_EP0RCVOUT also require EasyDMA
+ if ( _dcd.dma_pending )
+ {
+ // use usbd task to defer later
+ usbd_defer_func( (osal_task_func_t) start_ep0_task, (void*) &NRF_USBD->TASKS_EP0RCVOUT, true );
+ }else
+ {
+ start_ep0_task(&NRF_USBD->TASKS_EP0RCVOUT);
+ }
}else
{
// nRF auto accept next Bulk/Interrupt OUT packet
@@ -973,7 +996,7 @@ void tusb_hal_nrf_power_event (uint32_t event)
hfclk_disable();
- dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) ? true : false);
+ dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, is_in_isr());
}
break;