summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHa Thach <[email protected]>2021-09-18 23:12:40 +0700
committerGitHub <[email protected]>2021-09-18 23:12:40 +0700
commit3e569f8e79160538e1b055aba352246abb6c3dd0 (patch)
tree28942e7b9b8efc40af6e9d020fff9a155402bc02
parent90465299b42facff3c815d97950066706dbbd74a (diff)
parenta71ac71d7f9fda4f72b02148a194987821864fa4 (diff)
Merge pull request #1094 from kasjer/kasjer/da146xx-vbus-handling
dcd_da146xx: Add VBUS handling
-rw-r--r--hw/bsp/da14695_dk_usb/da14695_dk_usb.c9
-rw-r--r--hw/bsp/da1469x_dk_pro/da1469x-dk-pro.c26
-rw-r--r--src/portable/dialog/da146xx/dcd_da146xx.c65
3 files changed, 83 insertions, 17 deletions
diff --git a/hw/bsp/da14695_dk_usb/da14695_dk_usb.c b/hw/bsp/da14695_dk_usb/da14695_dk_usb.c
index e7c7ae364..bdb30e0e5 100644
--- a/hw/bsp/da14695_dk_usb/da14695_dk_usb.c
+++ b/hw/bsp/da14695_dk_usb/da14695_dk_usb.c
@@ -53,6 +53,9 @@ void UnhandledIRQ(void)
while(1);
}
+// DA146xx driver function that must be called whenever VBUS changes.
+extern void tusb_vbus_changed(bool present);
+
void board_init(void)
{
// LED
@@ -70,7 +73,10 @@ void board_init(void)
// 1ms tick timer
SysTick_Config(SystemCoreClock / 1000);
- NVIC_SetPriority(USB_IRQn, 2);
+#if TUSB_OPT_DEVICE_ENABLED
+ // This board is USB powered there is no need to monitor
+ // VBUS line. Notify driver that VBUS is present.
+ tusb_vbus_changed(true);
/* Setup USB IRQ */
NVIC_SetPriority(USB_IRQn, 2);
@@ -81,6 +87,7 @@ void board_init(void)
mcu_gpio_set_pin_function(14, MCU_GPIO_MODE_INPUT, MCU_GPIO_FUNC_USB);
mcu_gpio_set_pin_function(15, MCU_GPIO_MODE_INPUT, MCU_GPIO_FUNC_USB);
+#endif
}
//--------------------------------------------------------------------+
diff --git a/hw/bsp/da1469x_dk_pro/da1469x-dk-pro.c b/hw/bsp/da1469x_dk_pro/da1469x-dk-pro.c
index 85fa17152..2b6931e4e 100644
--- a/hw/bsp/da1469x_dk_pro/da1469x-dk-pro.c
+++ b/hw/bsp/da1469x_dk_pro/da1469x-dk-pro.c
@@ -36,6 +36,21 @@ void USB_IRQHandler(void)
tud_int_handler(0);
}
+#if TUSB_OPT_DEVICE_ENABLED
+// DA146xx driver function that must be called whenever VBUS changes
+extern void tusb_vbus_changed(bool present);
+
+// VBUS change interrupt handler
+void VBUS_IRQHandler(void)
+{
+ bool present = (CRG_TOP->ANA_STATUS_REG & CRG_TOP_ANA_STATUS_REG_VBUS_AVAILABLE_Msk) != 0;
+ // Clear VBUS interrupt
+ CRG_TOP->VBUS_IRQ_CLEAR_REG = 1;
+
+ tusb_vbus_changed(present);
+}
+#endif
+
//--------------------------------------------------------------------+
// MACRO TYPEDEF CONSTANT ENUM
//--------------------------------------------------------------------+
@@ -70,7 +85,15 @@ void board_init(void)
// 1ms tick timer
SysTick_Config(SystemCoreClock / 1000);
- NVIC_SetPriority(USB_IRQn, 2);
+#if TUSB_OPT_DEVICE_ENABLED
+ // Setup interrupt for both connect and disconnect
+ CRG_TOP->VBUS_IRQ_MASK_REG = CRG_TOP_VBUS_IRQ_MASK_REG_VBUS_IRQ_EN_FALL_Msk |
+ CRG_TOP_VBUS_IRQ_MASK_REG_VBUS_IRQ_EN_RISE_Msk;
+ NVIC_SetPriority(VBUS_IRQn, 2);
+ // Trigger interrupt at the start to inform driver about VBUS state at start
+ // otherwise it could go unnoticed.
+ NVIC_SetPendingIRQ(VBUS_IRQn);
+ NVIC_EnableIRQ(VBUS_IRQn);
/* Setup USB IRQ */
NVIC_SetPriority(USB_IRQn, 2);
@@ -81,6 +104,7 @@ void board_init(void)
mcu_gpio_set_pin_function(14, MCU_GPIO_MODE_INPUT, MCU_GPIO_FUNC_USB);
mcu_gpio_set_pin_function(15, MCU_GPIO_MODE_INPUT, MCU_GPIO_FUNC_USB);
+#endif
}
//--------------------------------------------------------------------+
diff --git a/src/portable/dialog/da146xx/dcd_da146xx.c b/src/portable/dialog/da146xx/dcd_da146xx.c
index 7b0d8f86c..112cdb502 100644
--- a/src/portable/dialog/da146xx/dcd_da146xx.c
+++ b/src/portable/dialog/da146xx/dcd_da146xx.c
@@ -217,6 +217,7 @@ typedef struct {
static struct
{
bool vbus_present;
+ bool init_called;
bool in_reset;
xfer_ctl_t xfer_status[EP_MAX][2];
// Endpoints that use DMA, one for each direction
@@ -224,6 +225,7 @@ static struct
} _dcd =
{
.vbus_present = false,
+ .init_called = false,
.xfer_status =
{
{ { .regs = EP_REGS(USB_EPC0_REG) }, { .regs = EP_REGS(USB_EPC0_REG) } },
@@ -735,19 +737,13 @@ static void handle_ep0_nak(void)
*------------------------------------------------------------------*/
void dcd_init(uint8_t rhport)
{
- USB->USB_MCTRL_REG = USB_USB_MCTRL_REG_USBEN_Msk;
- USB->USB_NFSR_REG = 0;
- USB->USB_FAR_REG = 0x80;
- USB->USB_NFSR_REG = NFSR_NODE_RESET;
- USB->USB_TXMSK_REG = 0;
- USB->USB_RXMSK_REG = 0;
-
- USB->USB_MAMSK_REG = USB_USB_MAMSK_REG_USB_M_INTR_Msk |
- USB_USB_MAMSK_REG_USB_M_ALT_Msk |
- USB_USB_MAMSK_REG_USB_M_WARN_Msk;
- USB->USB_ALTMSK_REG = USB_USB_ALTMSK_REG_USB_M_RESET_Msk;
+ (void) rhport;
- dcd_connect(rhport);
+ _dcd.init_called = true;
+ if (_dcd.vbus_present)
+ {
+ dcd_connect(rhport);
+ }
}
void dcd_int_enable(uint8_t rhport)
@@ -783,10 +779,25 @@ void dcd_connect(uint8_t rhport)
{
(void)rhport;
- REG_SET_BIT(USB_MCTRL_REG, USB_NAT);
+ if (GET_BIT(USB->USB_MCTRL_REG, USB_USB_MCTRL_REG_USB_NAT) == 0)
+ {
+ USB->USB_MCTRL_REG = USB_USB_MCTRL_REG_USBEN_Msk;
+ USB->USB_NFSR_REG = 0;
+ USB->USB_FAR_REG = 0x80;
+ USB->USB_NFSR_REG = NFSR_NODE_RESET;
+ USB->USB_TXMSK_REG = 0;
+ USB->USB_RXMSK_REG = 0;
+
+ USB->USB_MAMSK_REG = USB_USB_MAMSK_REG_USB_M_INTR_Msk |
+ USB_USB_MAMSK_REG_USB_M_ALT_Msk |
+ USB_USB_MAMSK_REG_USB_M_WARN_Msk;
+ USB->USB_ALTMSK_REG = USB_USB_ALTMSK_REG_USB_M_RESET_Msk;
+
+ REG_SET_BIT(USB_MCTRL_REG, USB_NAT);
- // Select chosen DMA to be triggered by USB.
- DMA->DMA_REQ_MUX_REG = (DMA->DMA_REQ_MUX_REG & ~DA146XX_DMA_USB_MUX_MASK) | DA146XX_DMA_USB_MUX;
+ // Select chosen DMA to be triggered by USB.
+ DMA->DMA_REQ_MUX_REG = (DMA->DMA_REQ_MUX_REG & ~DA146XX_DMA_USB_MUX_MASK) | DA146XX_DMA_USB_MUX;
+ }
}
void dcd_disconnect(uint8_t rhport)
@@ -796,6 +807,30 @@ void dcd_disconnect(uint8_t rhport)
REG_CLR_BIT(USB_MCTRL_REG, USB_NAT);
}
+TU_ATTR_ALWAYS_INLINE static inline bool is_in_isr(void)
+{
+ return (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) != 0;
+}
+
+void tusb_vbus_changed(bool present)
+{
+ if (present && !_dcd.vbus_present)
+ {
+ _dcd.vbus_present = true;
+ // If power event happened before USB started, delay dcd_connect
+ // until dcd_init is called.
+ if (_dcd.init_called)
+ {
+ dcd_connect(0);
+ }
+ }
+ else if (!present && _dcd.vbus_present)
+ {
+ _dcd.vbus_present = false;
+ USB->USB_MCTRL_REG = 0;
+ dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, is_in_isr());
+ }
+}
/*------------------------------------------------------------------*/
/* DCD Endpoint port