mirror of
https://github.com/hathach/tinyusb.git
synced 2025-02-15 12:39:50 +00:00
commit
0fb73eac7e
@ -79,8 +79,7 @@
|
|||||||
/*------------------------------------------------------------------*/
|
/*------------------------------------------------------------------*/
|
||||||
/* MACRO TYPEDEF CONSTANT ENUM
|
/* MACRO TYPEDEF CONSTANT ENUM
|
||||||
*------------------------------------------------------------------*/
|
*------------------------------------------------------------------*/
|
||||||
enum
|
enum {
|
||||||
{
|
|
||||||
// Max allowed by USB specs
|
// Max allowed by USB specs
|
||||||
MAX_PACKET_SIZE = 64,
|
MAX_PACKET_SIZE = 64,
|
||||||
|
|
||||||
@ -89,15 +88,13 @@ enum
|
|||||||
USBD_INTENCLR_ENDISOIN_Msk | USBD_INTEN_ENDISOOUT_Msk
|
USBD_INTENCLR_ENDISOIN_Msk | USBD_INTEN_ENDISOOUT_Msk
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum {
|
||||||
{
|
|
||||||
EP_ISO_NUM = 8, // Endpoint number is fixed (8) for ISOOUT and ISOIN
|
EP_ISO_NUM = 8, // Endpoint number is fixed (8) for ISOOUT and ISOIN
|
||||||
EP_CBI_COUNT = 8 // Control Bulk Interrupt endpoints count
|
EP_CBI_COUNT = 8 // Control Bulk Interrupt endpoints count
|
||||||
};
|
};
|
||||||
|
|
||||||
// Transfer Descriptor
|
// Transfer Descriptor
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
|
||||||
uint8_t* buffer;
|
uint8_t* buffer;
|
||||||
uint16_t total_len;
|
uint16_t total_len;
|
||||||
volatile uint16_t actual_len;
|
volatile uint16_t actual_len;
|
||||||
@ -115,8 +112,7 @@ typedef struct
|
|||||||
} xfer_td_t;
|
} xfer_td_t;
|
||||||
|
|
||||||
// Data for managing dcd
|
// Data for managing dcd
|
||||||
static struct
|
static struct {
|
||||||
{
|
|
||||||
// All 8 endpoints including control IN & OUT (offset 1)
|
// All 8 endpoints including control IN & OUT (offset 1)
|
||||||
// +1 for ISO endpoints
|
// +1 for ISO endpoints
|
||||||
xfer_td_t xfer[EP_CBI_COUNT + 1][2];
|
xfer_td_t xfer[EP_CBI_COUNT + 1][2];
|
||||||
@ -130,83 +126,69 @@ static struct
|
|||||||
*------------------------------------------------------------------*/
|
*------------------------------------------------------------------*/
|
||||||
|
|
||||||
// check if we are in ISR
|
// check if we are in ISR
|
||||||
TU_ATTR_ALWAYS_INLINE static inline bool is_in_isr(void)
|
TU_ATTR_ALWAYS_INLINE static inline bool is_in_isr(void) {
|
||||||
{
|
|
||||||
return (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) ? true : false;
|
return (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// helper to start DMA
|
// helper to start DMA
|
||||||
static void start_dma(volatile uint32_t* reg_startep)
|
static void start_dma(volatile uint32_t* reg_startep) {
|
||||||
{
|
|
||||||
(*reg_startep) = 1;
|
(*reg_startep) = 1;
|
||||||
__ISB(); __DSB();
|
__ISB();
|
||||||
|
__DSB();
|
||||||
|
|
||||||
// TASKS_EP0STATUS, TASKS_EP0RCVOUT seem to need EasyDMA to be available
|
// TASKS_EP0STATUS, TASKS_EP0RCVOUT seem to need EasyDMA to be available
|
||||||
// However these don't trigger any DMA transfer and got ENDED event subsequently
|
// However these don't trigger any DMA transfer and got ENDED event subsequently
|
||||||
// Therefore dma_pending is corrected right away
|
// Therefore dma_pending is corrected right away
|
||||||
if ( (reg_startep == &NRF_USBD->TASKS_EP0STATUS) || (reg_startep == &NRF_USBD->TASKS_EP0RCVOUT) )
|
if ((reg_startep == &NRF_USBD->TASKS_EP0STATUS) || (reg_startep == &NRF_USBD->TASKS_EP0RCVOUT)) {
|
||||||
{
|
|
||||||
atomic_flag_clear(&_dcd.dma_running);
|
atomic_flag_clear(&_dcd.dma_running);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void edpt_dma_start(volatile uint32_t* reg_startep)
|
static void edpt_dma_start(volatile uint32_t* reg_startep) {
|
||||||
{
|
if (atomic_flag_test_and_set(&_dcd.dma_running)) {
|
||||||
if ( atomic_flag_test_and_set(&_dcd.dma_running) )
|
|
||||||
{
|
|
||||||
usbd_defer_func((osal_task_func_t) edpt_dma_start, (void*) (uintptr_t) reg_startep, true);
|
usbd_defer_func((osal_task_func_t) edpt_dma_start, (void*) (uintptr_t) reg_startep, true);
|
||||||
}else
|
} else {
|
||||||
{
|
|
||||||
start_dma(reg_startep);
|
start_dma(reg_startep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DMA is complete
|
// DMA is complete
|
||||||
static void edpt_dma_end(void)
|
static void edpt_dma_end(void) {
|
||||||
{
|
|
||||||
TU_ASSERT(_dcd.dma_running,);
|
TU_ASSERT(_dcd.dma_running,);
|
||||||
atomic_flag_clear(&_dcd.dma_running);
|
atomic_flag_clear(&_dcd.dma_running);
|
||||||
}
|
}
|
||||||
|
|
||||||
// helper getting td
|
// helper getting td
|
||||||
static inline xfer_td_t* get_td(uint8_t epnum, uint8_t dir)
|
static inline xfer_td_t* get_td(uint8_t epnum, uint8_t dir) {
|
||||||
{
|
|
||||||
return &_dcd.xfer[epnum][dir];
|
return &_dcd.xfer[epnum][dir];
|
||||||
}
|
}
|
||||||
|
|
||||||
static void xact_out_dma(uint8_t epnum);
|
static void xact_out_dma(uint8_t epnum);
|
||||||
|
|
||||||
// Function wraps xact_out_dma which wants uint8_t while usbd_defer_func wants void (*)(void *)
|
// Function wraps xact_out_dma which wants uint8_t while usbd_defer_func wants void (*)(void *)
|
||||||
static void xact_out_dma_wrapper(void *epnum)
|
static void xact_out_dma_wrapper(void* epnum) {
|
||||||
{
|
|
||||||
xact_out_dma((uint8_t) ((uintptr_t) epnum));
|
xact_out_dma((uint8_t) ((uintptr_t) epnum));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start DMA to move data from Endpoint -> RAM
|
// Start DMA to move data from Endpoint -> RAM
|
||||||
static void xact_out_dma(uint8_t epnum)
|
static void xact_out_dma(uint8_t epnum) {
|
||||||
{
|
|
||||||
xfer_td_t* xfer = get_td(epnum, TUSB_DIR_OUT);
|
xfer_td_t* xfer = get_td(epnum, TUSB_DIR_OUT);
|
||||||
uint32_t xact_len;
|
uint32_t xact_len;
|
||||||
|
|
||||||
// DMA can't be active during read of SIZE.EPOUT or SIZE.ISOOUT, so try to lock,
|
// DMA can't be active during read of SIZE.EPOUT or SIZE.ISOOUT, so try to lock,
|
||||||
// If already running defer call regardless if it was called from ISR or task,
|
// If already running defer call regardless if it was called from ISR or task,
|
||||||
if ( atomic_flag_test_and_set(&_dcd.dma_running) )
|
if (atomic_flag_test_and_set(&_dcd.dma_running)) {
|
||||||
{
|
|
||||||
usbd_defer_func((osal_task_func_t) xact_out_dma_wrapper, (void*) (uint32_t) epnum, is_in_isr());
|
usbd_defer_func((osal_task_func_t) xact_out_dma_wrapper, (void*) (uint32_t) epnum, is_in_isr());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (epnum == EP_ISO_NUM)
|
if (epnum == EP_ISO_NUM) {
|
||||||
{
|
|
||||||
xact_len = NRF_USBD->SIZE.ISOOUT;
|
xact_len = NRF_USBD->SIZE.ISOOUT;
|
||||||
// If ZERO bit is set, ignore ISOOUT length
|
// If ZERO bit is set, ignore ISOOUT length
|
||||||
if (xact_len & USBD_SIZE_ISOOUT_ZERO_Msk)
|
if (xact_len & USBD_SIZE_ISOOUT_ZERO_Msk) {
|
||||||
{
|
|
||||||
xact_len = 0;
|
xact_len = 0;
|
||||||
atomic_flag_clear(&_dcd.dma_running);
|
atomic_flag_clear(&_dcd.dma_running);
|
||||||
}
|
} else {
|
||||||
else
|
if (xfer->started) {
|
||||||
{
|
|
||||||
if (xfer->started)
|
|
||||||
{
|
|
||||||
// Trigger DMA move data from Endpoint -> SRAM
|
// Trigger DMA move data from Endpoint -> SRAM
|
||||||
NRF_USBD->ISOOUT.PTR = (uint32_t) xfer->buffer;
|
NRF_USBD->ISOOUT.PTR = (uint32_t) xfer->buffer;
|
||||||
NRF_USBD->ISOOUT.MAXCNT = xact_len;
|
NRF_USBD->ISOOUT.MAXCNT = xact_len;
|
||||||
@ -216,9 +198,7 @@ static void xact_out_dma(uint8_t epnum)
|
|||||||
atomic_flag_clear(&_dcd.dma_running);
|
atomic_flag_clear(&_dcd.dma_running);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
// limit xact len to remaining length
|
// limit xact len to remaining length
|
||||||
xact_len = tu_min16((uint16_t) NRF_USBD->SIZE.EPOUT[epnum], xfer->total_len - xfer->actual_len);
|
xact_len = tu_min16((uint16_t) NRF_USBD->SIZE.EPOUT[epnum], xfer->total_len - xfer->actual_len);
|
||||||
|
|
||||||
@ -232,8 +212,7 @@ static void xact_out_dma(uint8_t epnum)
|
|||||||
|
|
||||||
// Prepare for a CBI transaction IN, call at the start
|
// Prepare for a CBI transaction IN, call at the start
|
||||||
// it start DMA to transfer data from RAM -> Endpoint
|
// it start DMA to transfer data from RAM -> Endpoint
|
||||||
static void xact_in_dma(uint8_t epnum)
|
static void xact_in_dma(uint8_t epnum) {
|
||||||
{
|
|
||||||
xfer_td_t* xfer = get_td(epnum, TUSB_DIR_IN);
|
xfer_td_t* xfer = get_td(epnum, TUSB_DIR_IN);
|
||||||
|
|
||||||
// Each transaction is up to Max Packet Size
|
// Each transaction is up to Max Packet Size
|
||||||
@ -248,26 +227,22 @@ static void xact_in_dma(uint8_t epnum)
|
|||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
// Controller API
|
// Controller API
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
void dcd_init (uint8_t rhport)
|
void dcd_init(uint8_t rhport) {
|
||||||
{
|
|
||||||
TU_LOG2("dcd init\r\n");
|
TU_LOG2("dcd init\r\n");
|
||||||
(void) rhport;
|
(void) rhport;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dcd_int_enable(uint8_t rhport)
|
void dcd_int_enable(uint8_t rhport) {
|
||||||
{
|
|
||||||
(void) rhport;
|
(void) rhport;
|
||||||
NVIC_EnableIRQ(USBD_IRQn);
|
NVIC_EnableIRQ(USBD_IRQn);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dcd_int_disable(uint8_t rhport)
|
void dcd_int_disable(uint8_t rhport) {
|
||||||
{
|
|
||||||
(void) rhport;
|
(void) rhport;
|
||||||
NVIC_DisableIRQ(USBD_IRQn);
|
NVIC_DisableIRQ(USBD_IRQn);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dcd_set_address (uint8_t rhport, uint8_t dev_addr)
|
void dcd_set_address(uint8_t rhport, uint8_t dev_addr) {
|
||||||
{
|
|
||||||
(void) rhport;
|
(void) rhport;
|
||||||
(void) dev_addr;
|
(void) dev_addr;
|
||||||
// Set Address is automatically update by hw controller, nothing to do
|
// Set Address is automatically update by hw controller, nothing to do
|
||||||
@ -282,8 +257,7 @@ void dcd_set_address (uint8_t rhport, uint8_t dev_addr)
|
|||||||
NRF_USBD->INTENSET = USBD_INTEN_USBEVENT_Msk;
|
NRF_USBD->INTENSET = USBD_INTEN_USBEVENT_Msk;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dcd_remote_wakeup(uint8_t rhport)
|
void dcd_remote_wakeup(uint8_t rhport) {
|
||||||
{
|
|
||||||
(void) rhport;
|
(void) rhport;
|
||||||
|
|
||||||
// Bring controller out of low power mode
|
// Bring controller out of low power mode
|
||||||
@ -292,8 +266,7 @@ void dcd_remote_wakeup(uint8_t rhport)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// disconnect by disabling internal pull-up resistor on D+/D-
|
// disconnect by disabling internal pull-up resistor on D+/D-
|
||||||
void dcd_disconnect(uint8_t rhport)
|
void dcd_disconnect(uint8_t rhport) {
|
||||||
{
|
|
||||||
(void) rhport;
|
(void) rhport;
|
||||||
NRF_USBD->USBPULLUP = 0;
|
NRF_USBD->USBPULLUP = 0;
|
||||||
|
|
||||||
@ -303,14 +276,12 @@ void dcd_disconnect(uint8_t rhport)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// connect by enabling internal pull-up resistor on D+/D-
|
// connect by enabling internal pull-up resistor on D+/D-
|
||||||
void dcd_connect(uint8_t rhport)
|
void dcd_connect(uint8_t rhport) {
|
||||||
{
|
|
||||||
(void) rhport;
|
(void) rhport;
|
||||||
NRF_USBD->USBPULLUP = 1;
|
NRF_USBD->USBPULLUP = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dcd_sof_enable(uint8_t rhport, bool en)
|
void dcd_sof_enable(uint8_t rhport, bool en) {
|
||||||
{
|
|
||||||
(void) rhport;
|
(void) rhport;
|
||||||
(void) en;
|
(void) en;
|
||||||
|
|
||||||
@ -320,8 +291,7 @@ void dcd_sof_enable(uint8_t rhport, bool en)
|
|||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
// Endpoint API
|
// Endpoint API
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt)
|
bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const* desc_edpt) {
|
||||||
{
|
|
||||||
(void) rhport;
|
(void) rhport;
|
||||||
|
|
||||||
uint8_t const ep_addr = desc_edpt->bEndpointAddress;
|
uint8_t const ep_addr = desc_edpt->bEndpointAddress;
|
||||||
@ -330,29 +300,23 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt)
|
|||||||
|
|
||||||
_dcd.xfer[epnum][dir].mps = tu_edpt_packet_size(desc_edpt);
|
_dcd.xfer[epnum][dir].mps = tu_edpt_packet_size(desc_edpt);
|
||||||
|
|
||||||
if (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS)
|
if (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS) {
|
||||||
{
|
if (dir == TUSB_DIR_OUT) {
|
||||||
if (dir == TUSB_DIR_OUT)
|
|
||||||
{
|
|
||||||
NRF_USBD->INTENSET = TU_BIT(USBD_INTEN_ENDEPOUT0_Pos + epnum);
|
NRF_USBD->INTENSET = TU_BIT(USBD_INTEN_ENDEPOUT0_Pos + epnum);
|
||||||
NRF_USBD->EPOUTEN |= TU_BIT(epnum);
|
NRF_USBD->EPOUTEN |= TU_BIT(epnum);
|
||||||
|
|
||||||
// Write any value to SIZE register will allow nRF to ACK/accept data
|
// Write any value to SIZE register will allow nRF to ACK/accept data
|
||||||
NRF_USBD->SIZE.EPOUT[epnum] = 0;
|
NRF_USBD->SIZE.EPOUT[epnum] = 0;
|
||||||
}else
|
} else {
|
||||||
{
|
|
||||||
NRF_USBD->INTENSET = TU_BIT(USBD_INTEN_ENDEPIN0_Pos + epnum);
|
NRF_USBD->INTENSET = TU_BIT(USBD_INTEN_ENDEPIN0_Pos + epnum);
|
||||||
NRF_USBD->EPINEN |= TU_BIT(epnum);
|
NRF_USBD->EPINEN |= TU_BIT(epnum);
|
||||||
}
|
}
|
||||||
// clear stall and reset DataToggle
|
// clear stall and reset DataToggle
|
||||||
NRF_USBD->EPSTALL = (USBD_EPSTALL_STALL_UnStall << USBD_EPSTALL_STALL_Pos) | ep_addr;
|
NRF_USBD->EPSTALL = (USBD_EPSTALL_STALL_UnStall << USBD_EPSTALL_STALL_Pos) | ep_addr;
|
||||||
NRF_USBD->DTOGGLE = (USBD_DTOGGLE_VALUE_Data0 << USBD_DTOGGLE_VALUE_Pos) | ep_addr;
|
NRF_USBD->DTOGGLE = (USBD_DTOGGLE_VALUE_Data0 << USBD_DTOGGLE_VALUE_Pos) | ep_addr;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
TU_ASSERT(epnum == EP_ISO_NUM);
|
TU_ASSERT(epnum == EP_ISO_NUM);
|
||||||
if (dir == TUSB_DIR_OUT)
|
if (dir == TUSB_DIR_OUT) {
|
||||||
{
|
|
||||||
// SPLIT ISO buffer when ISO IN endpoint is already opened.
|
// SPLIT ISO buffer when ISO IN endpoint is already opened.
|
||||||
if (_dcd.xfer[EP_ISO_NUM][TUSB_DIR_IN].mps) NRF_USBD->ISOSPLIT = USBD_ISOSPLIT_SPLIT_HalfIN;
|
if (_dcd.xfer[EP_ISO_NUM][TUSB_DIR_IN].mps) NRF_USBD->ISOSPLIT = USBD_ISOSPLIT_SPLIT_HalfIN;
|
||||||
|
|
||||||
@ -365,9 +329,7 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt)
|
|||||||
// Enable SOF and ISOOUT interrupts, and ISOOUT endpoint.
|
// Enable SOF and ISOOUT interrupts, and ISOOUT endpoint.
|
||||||
NRF_USBD->INTENSET = USBD_INTENSET_ENDISOOUT_Msk | USBD_INTENSET_SOF_Msk;
|
NRF_USBD->INTENSET = USBD_INTENSET_ENDISOOUT_Msk | USBD_INTENSET_SOF_Msk;
|
||||||
NRF_USBD->EPOUTEN |= USBD_EPOUTEN_ISOOUT_Msk;
|
NRF_USBD->EPOUTEN |= USBD_EPOUTEN_ISOOUT_Msk;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
NRF_USBD->EVENTS_ENDISOIN = 0;
|
NRF_USBD->EVENTS_ENDISOIN = 0;
|
||||||
|
|
||||||
// SPLIT ISO buffer when ISO OUT endpoint is already opened.
|
// SPLIT ISO buffer when ISO OUT endpoint is already opened.
|
||||||
@ -382,19 +344,18 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
__ISB(); __DSB();
|
__ISB();
|
||||||
|
__DSB();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dcd_edpt_close_all (uint8_t rhport)
|
void dcd_edpt_close_all(uint8_t rhport) {
|
||||||
{
|
|
||||||
// disable interrupt to prevent race condition
|
// disable interrupt to prevent race condition
|
||||||
dcd_int_disable(rhport);
|
dcd_int_disable(rhport);
|
||||||
|
|
||||||
// disable all non-control (bulk + interrupt) endpoints
|
// disable all non-control (bulk + interrupt) endpoints
|
||||||
for ( uint8_t ep = 1; ep < EP_CBI_COUNT; ep++ )
|
for (uint8_t ep = 1; ep < EP_CBI_COUNT; ep++) {
|
||||||
{
|
|
||||||
NRF_USBD->INTENCLR = TU_BIT(USBD_INTEN_ENDEPOUT0_Pos + ep) | TU_BIT(USBD_INTEN_ENDEPIN0_Pos + ep);
|
NRF_USBD->INTENCLR = TU_BIT(USBD_INTEN_ENDEPOUT0_Pos + ep) | TU_BIT(USBD_INTEN_ENDEPIN0_Pos + ep);
|
||||||
|
|
||||||
NRF_USBD->TASKS_STARTEPIN[ep] = 0;
|
NRF_USBD->TASKS_STARTEPIN[ep] = 0;
|
||||||
@ -419,53 +380,44 @@ void dcd_edpt_close_all (uint8_t rhport)
|
|||||||
dcd_int_enable(rhport);
|
dcd_int_enable(rhport);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr)
|
void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) {
|
||||||
{
|
|
||||||
(void) rhport;
|
(void) rhport;
|
||||||
|
|
||||||
uint8_t const epnum = tu_edpt_number(ep_addr);
|
uint8_t const epnum = tu_edpt_number(ep_addr);
|
||||||
uint8_t const dir = tu_edpt_dir(ep_addr);
|
uint8_t const dir = tu_edpt_dir(ep_addr);
|
||||||
|
|
||||||
if (epnum != EP_ISO_NUM)
|
if (epnum != EP_ISO_NUM) {
|
||||||
{
|
|
||||||
// CBI
|
// CBI
|
||||||
if (dir == TUSB_DIR_OUT)
|
if (dir == TUSB_DIR_OUT) {
|
||||||
{
|
|
||||||
NRF_USBD->INTENCLR = TU_BIT(USBD_INTEN_ENDEPOUT0_Pos + epnum);
|
NRF_USBD->INTENCLR = TU_BIT(USBD_INTEN_ENDEPOUT0_Pos + epnum);
|
||||||
NRF_USBD->EPOUTEN &= ~TU_BIT(epnum);
|
NRF_USBD->EPOUTEN &= ~TU_BIT(epnum);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
NRF_USBD->INTENCLR = TU_BIT(USBD_INTEN_ENDEPIN0_Pos + epnum);
|
NRF_USBD->INTENCLR = TU_BIT(USBD_INTEN_ENDEPIN0_Pos + epnum);
|
||||||
NRF_USBD->EPINEN &= ~TU_BIT(epnum);
|
NRF_USBD->EPINEN &= ~TU_BIT(epnum);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
_dcd.xfer[EP_ISO_NUM][dir].mps = 0;
|
_dcd.xfer[EP_ISO_NUM][dir].mps = 0;
|
||||||
// ISO
|
// ISO
|
||||||
if (dir == TUSB_DIR_OUT)
|
if (dir == TUSB_DIR_OUT) {
|
||||||
{
|
|
||||||
NRF_USBD->INTENCLR = USBD_INTENCLR_ENDISOOUT_Msk;
|
NRF_USBD->INTENCLR = USBD_INTENCLR_ENDISOOUT_Msk;
|
||||||
NRF_USBD->EPOUTEN &= ~USBD_EPOUTEN_ISOOUT_Msk;
|
NRF_USBD->EPOUTEN &= ~USBD_EPOUTEN_ISOOUT_Msk;
|
||||||
NRF_USBD->EVENTS_ENDISOOUT = 0;
|
NRF_USBD->EVENTS_ENDISOOUT = 0;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
NRF_USBD->INTENCLR = USBD_INTENCLR_ENDISOIN_Msk;
|
NRF_USBD->INTENCLR = USBD_INTENCLR_ENDISOIN_Msk;
|
||||||
NRF_USBD->EPINEN &= ~USBD_EPINEN_ISOIN_Msk;
|
NRF_USBD->EPINEN &= ~USBD_EPINEN_ISOIN_Msk;
|
||||||
}
|
}
|
||||||
// One of the ISO endpoints closed, no need to split buffers any more.
|
// One of the ISO endpoints closed, no need to split buffers any more.
|
||||||
NRF_USBD->ISOSPLIT = USBD_ISOSPLIT_SPLIT_OneDir;
|
NRF_USBD->ISOSPLIT = USBD_ISOSPLIT_SPLIT_OneDir;
|
||||||
// When both ISO endpoint are close there is no need for SOF any more.
|
// When both ISO endpoint are close there is no need for SOF any more.
|
||||||
if (_dcd.xfer[EP_ISO_NUM][TUSB_DIR_IN].mps + _dcd.xfer[EP_ISO_NUM][TUSB_DIR_OUT].mps == 0) NRF_USBD->INTENCLR = USBD_INTENCLR_SOF_Msk;
|
if (_dcd.xfer[EP_ISO_NUM][TUSB_DIR_IN].mps + _dcd.xfer[EP_ISO_NUM][TUSB_DIR_OUT].mps == 0)
|
||||||
|
NRF_USBD->INTENCLR = USBD_INTENCLR_SOF_Msk;
|
||||||
}
|
}
|
||||||
_dcd.xfer[epnum][dir].started = false;
|
_dcd.xfer[epnum][dir].started = false;
|
||||||
__ISB(); __DSB();
|
__ISB();
|
||||||
|
__DSB();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes)
|
bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) {
|
||||||
{
|
|
||||||
(void) rhport;
|
(void) rhport;
|
||||||
|
|
||||||
uint8_t const epnum = tu_edpt_number(ep_addr);
|
uint8_t const epnum = tu_edpt_number(ep_addr);
|
||||||
@ -481,45 +433,36 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t
|
|||||||
// Control endpoint with zero-length packet and opposite direction to 1st request byte --> status stage
|
// Control endpoint with zero-length packet and opposite direction to 1st request byte --> status stage
|
||||||
bool const control_status = (epnum == 0 && total_bytes == 0 && dir != tu_edpt_dir(NRF_USBD->BMREQUESTTYPE));
|
bool const control_status = (epnum == 0 && total_bytes == 0 && dir != tu_edpt_dir(NRF_USBD->BMREQUESTTYPE));
|
||||||
|
|
||||||
if ( control_status )
|
if (control_status) {
|
||||||
{
|
|
||||||
// Status Phase also requires EasyDMA has to be available as well !!!!
|
// Status Phase also requires EasyDMA has to be available as well !!!!
|
||||||
edpt_dma_start(&NRF_USBD->TASKS_EP0STATUS);
|
edpt_dma_start(&NRF_USBD->TASKS_EP0STATUS);
|
||||||
|
|
||||||
// The nRF doesn't interrupt on status transmit so we queue up a success response.
|
// 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, is_in_isr());
|
dcd_event_xfer_complete(0, ep_addr, 0, XFER_RESULT_SUCCESS, is_in_isr());
|
||||||
}
|
} else if (dir == TUSB_DIR_OUT) {
|
||||||
else if ( dir == TUSB_DIR_OUT )
|
|
||||||
{
|
|
||||||
xfer->started = true;
|
xfer->started = true;
|
||||||
if ( epnum == 0 )
|
if (epnum == 0) {
|
||||||
{
|
|
||||||
// Accept next Control Out packet. TASKS_EP0RCVOUT also require EasyDMA
|
// Accept next Control Out packet. TASKS_EP0RCVOUT also require EasyDMA
|
||||||
edpt_dma_start(&NRF_USBD->TASKS_EP0RCVOUT);
|
edpt_dma_start(&NRF_USBD->TASKS_EP0RCVOUT);
|
||||||
}else
|
} else {
|
||||||
{
|
|
||||||
// started just set, it could start DMA transfer if interrupt was trigger after this line
|
// started just set, it could start DMA transfer if interrupt was trigger after this line
|
||||||
// code only needs to start transfer (from Endpoint to RAM) when data_received was set
|
// code only needs to start transfer (from Endpoint to RAM) when data_received was set
|
||||||
// before started was set. If started is NOT set but data_received is, it means that
|
// before started was set. If started is NOT set but data_received is, it means that
|
||||||
// current transfer was already finished and next data is already present in endpoint and
|
// current transfer was already finished and next data is already present in endpoint and
|
||||||
// can be consumed by future transfer
|
// can be consumed by future transfer
|
||||||
__ISB(); __DSB();
|
__ISB();
|
||||||
if ( xfer->data_received && xfer->started )
|
__DSB();
|
||||||
{
|
if (xfer->data_received && xfer->started) {
|
||||||
// Data is already received previously
|
// Data is already received previously
|
||||||
// start DMA to copy to SRAM
|
// start DMA to copy to SRAM
|
||||||
xfer->data_received = false;
|
xfer->data_received = false;
|
||||||
xact_out_dma(epnum);
|
xact_out_dma(epnum);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
// nRF auto accept next Bulk/Interrupt OUT packet
|
// nRF auto accept next Bulk/Interrupt OUT packet
|
||||||
// nothing to do
|
// nothing to do
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
// Start DMA to copy data from RAM -> Endpoint
|
// Start DMA to copy data from RAM -> Endpoint
|
||||||
xact_in_dma(epnum);
|
xact_in_dma(epnum);
|
||||||
}
|
}
|
||||||
@ -527,8 +470,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr)
|
void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) {
|
||||||
{
|
|
||||||
(void) rhport;
|
(void) rhport;
|
||||||
|
|
||||||
uint8_t const epnum = tu_edpt_number(ep_addr);
|
uint8_t const epnum = tu_edpt_number(ep_addr);
|
||||||
@ -536,33 +478,29 @@ void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr)
|
|||||||
|
|
||||||
xfer_td_t* xfer = get_td(epnum, dir);
|
xfer_td_t* xfer = get_td(epnum, dir);
|
||||||
|
|
||||||
if ( epnum == 0 )
|
if (epnum == 0) {
|
||||||
{
|
|
||||||
NRF_USBD->TASKS_EP0STALL = 1;
|
NRF_USBD->TASKS_EP0STALL = 1;
|
||||||
}else if (epnum != EP_ISO_NUM)
|
} else if (epnum != EP_ISO_NUM) {
|
||||||
{
|
|
||||||
NRF_USBD->EPSTALL = (USBD_EPSTALL_STALL_Stall << USBD_EPSTALL_STALL_Pos) | ep_addr;
|
NRF_USBD->EPSTALL = (USBD_EPSTALL_STALL_Stall << USBD_EPSTALL_STALL_Pos) | ep_addr;
|
||||||
|
|
||||||
// Note: nRF can auto ACK packet OUT before get stalled.
|
// Note: nRF can auto ACK packet OUT before get stalled.
|
||||||
// There maybe data in endpoint fifo already, we need to pull it out
|
// There maybe data in endpoint fifo already, we need to pull it out
|
||||||
if ( (dir == TUSB_DIR_OUT) && xfer->data_received )
|
if ((dir == TUSB_DIR_OUT) && xfer->data_received) {
|
||||||
{
|
|
||||||
xfer->data_received = false;
|
xfer->data_received = false;
|
||||||
xact_out_dma(epnum);
|
xact_out_dma(epnum);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
__ISB(); __DSB();
|
__ISB();
|
||||||
|
__DSB();
|
||||||
}
|
}
|
||||||
|
|
||||||
void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr)
|
void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) {
|
||||||
{
|
|
||||||
(void) rhport;
|
(void) rhport;
|
||||||
uint8_t const epnum = tu_edpt_number(ep_addr);
|
uint8_t const epnum = tu_edpt_number(ep_addr);
|
||||||
uint8_t const dir = tu_edpt_dir(ep_addr);
|
uint8_t const dir = tu_edpt_dir(ep_addr);
|
||||||
|
|
||||||
if ( epnum != 0 && epnum != EP_ISO_NUM )
|
if (epnum != 0 && epnum != EP_ISO_NUM) {
|
||||||
{
|
|
||||||
// reset data toggle to DATA0
|
// reset data toggle to DATA0
|
||||||
// First write this register with VALUE=Nop to select the endpoint, then either read it to get the status from
|
// First write this register with VALUE=Nop to select the endpoint, then either read it to get the status from
|
||||||
// VALUE, or write it again with VALUE=Data0 or Data1
|
// VALUE, or write it again with VALUE=Data0 or Data1
|
||||||
@ -575,21 +513,20 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr)
|
|||||||
// Write any value to SIZE register will allow nRF to ACK/accept data
|
// Write any value to SIZE register will allow nRF to ACK/accept data
|
||||||
if (dir == TUSB_DIR_OUT) NRF_USBD->SIZE.EPOUT[epnum] = 0;
|
if (dir == TUSB_DIR_OUT) NRF_USBD->SIZE.EPOUT[epnum] = 0;
|
||||||
|
|
||||||
__ISB(); __DSB();
|
__ISB();
|
||||||
|
__DSB();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*------------------------------------------------------------------*/
|
/*------------------------------------------------------------------*/
|
||||||
/* Interrupt Handler
|
/* Interrupt Handler
|
||||||
*------------------------------------------------------------------*/
|
*------------------------------------------------------------------*/
|
||||||
void bus_reset(void)
|
void bus_reset(void) {
|
||||||
{
|
|
||||||
// 6.35.6 USB controller automatically disabled all endpoints (except control)
|
// 6.35.6 USB controller automatically disabled all endpoints (except control)
|
||||||
NRF_USBD->EPOUTEN = 1UL;
|
NRF_USBD->EPOUTEN = 1UL;
|
||||||
NRF_USBD->EPINEN = 1UL;
|
NRF_USBD->EPINEN = 1UL;
|
||||||
|
|
||||||
for(int i=0; i<8; i++)
|
for (int i = 0; i < 8; i++) {
|
||||||
{
|
|
||||||
NRF_USBD->TASKS_STARTEPIN[i] = 0;
|
NRF_USBD->TASKS_STARTEPIN[i] = 0;
|
||||||
NRF_USBD->TASKS_STARTEPOUT[i] = 0;
|
NRF_USBD->TASKS_STARTEPOUT[i] = 0;
|
||||||
}
|
}
|
||||||
@ -604,15 +541,15 @@ void bus_reset(void)
|
|||||||
// Reset interrupt
|
// Reset interrupt
|
||||||
NRF_USBD->INTENCLR = NRF_USBD->INTEN;
|
NRF_USBD->INTENCLR = NRF_USBD->INTEN;
|
||||||
NRF_USBD->INTENSET = USBD_INTEN_USBRESET_Msk | USBD_INTEN_USBEVENT_Msk | USBD_INTEN_EPDATA_Msk |
|
NRF_USBD->INTENSET = USBD_INTEN_USBRESET_Msk | USBD_INTEN_USBEVENT_Msk | USBD_INTEN_EPDATA_Msk |
|
||||||
USBD_INTEN_EP0SETUP_Msk | USBD_INTEN_EP0DATADONE_Msk | USBD_INTEN_ENDEPIN0_Msk | USBD_INTEN_ENDEPOUT0_Msk;
|
USBD_INTEN_EP0SETUP_Msk | USBD_INTEN_EP0DATADONE_Msk | USBD_INTEN_ENDEPIN0_Msk |
|
||||||
|
USBD_INTEN_ENDEPOUT0_Msk;
|
||||||
|
|
||||||
tu_varclr(&_dcd);
|
tu_varclr(&_dcd);
|
||||||
_dcd.xfer[0][TUSB_DIR_IN].mps = MAX_PACKET_SIZE;
|
_dcd.xfer[0][TUSB_DIR_IN].mps = MAX_PACKET_SIZE;
|
||||||
_dcd.xfer[0][TUSB_DIR_OUT].mps = MAX_PACKET_SIZE;
|
_dcd.xfer[0][TUSB_DIR_OUT].mps = MAX_PACKET_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dcd_int_handler(uint8_t rhport)
|
void dcd_int_handler(uint8_t rhport) {
|
||||||
{
|
|
||||||
(void) rhport;
|
(void) rhport;
|
||||||
|
|
||||||
uint32_t const inten = NRF_USBD->INTEN;
|
uint32_t const inten = NRF_USBD->INTEN;
|
||||||
@ -620,27 +557,24 @@ void dcd_int_handler(uint8_t rhport)
|
|||||||
|
|
||||||
volatile uint32_t* regevt = &NRF_USBD->EVENTS_USBRESET;
|
volatile uint32_t* regevt = &NRF_USBD->EVENTS_USBRESET;
|
||||||
|
|
||||||
for(uint8_t i=0; i<USBD_INTEN_EPDATA_Pos+1; i++)
|
for (uint8_t i = 0; i < USBD_INTEN_EPDATA_Pos + 1; i++) {
|
||||||
{
|
if (tu_bit_test(inten, i) && regevt[i]) {
|
||||||
if ( tu_bit_test(inten, i) && regevt[i] )
|
|
||||||
{
|
|
||||||
int_status |= TU_BIT(i);
|
int_status |= TU_BIT(i);
|
||||||
|
|
||||||
// event clear
|
// event clear
|
||||||
regevt[i] = 0;
|
regevt[i] = 0;
|
||||||
__ISB(); __DSB();
|
__ISB();
|
||||||
|
__DSB();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( int_status & USBD_INTEN_USBRESET_Msk )
|
if (int_status & USBD_INTEN_USBRESET_Msk) {
|
||||||
{
|
|
||||||
bus_reset();
|
bus_reset();
|
||||||
dcd_event_bus_reset(0, TUSB_SPEED_FULL, true);
|
dcd_event_bus_reset(0, TUSB_SPEED_FULL, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ISOIN: Data was moved to endpoint buffer, client will be notified in SOF
|
// ISOIN: Data was moved to endpoint buffer, client will be notified in SOF
|
||||||
if ( int_status & USBD_INTEN_ENDISOIN_Msk )
|
if (int_status & USBD_INTEN_ENDISOIN_Msk) {
|
||||||
{
|
|
||||||
xfer_td_t* xfer = get_td(EP_ISO_NUM, TUSB_DIR_IN);
|
xfer_td_t* xfer = get_td(EP_ISO_NUM, TUSB_DIR_IN);
|
||||||
|
|
||||||
xfer->actual_len = NRF_USBD->ISOIN.AMOUNT;
|
xfer->actual_len = NRF_USBD->ISOIN.AMOUNT;
|
||||||
@ -649,13 +583,11 @@ void dcd_int_handler(uint8_t rhport)
|
|||||||
xfer->iso_in_transfer_ready = true;
|
xfer->iso_in_transfer_ready = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( int_status & USBD_INTEN_SOF_Msk )
|
if (int_status & USBD_INTEN_SOF_Msk) {
|
||||||
{
|
|
||||||
bool iso_enabled = false;
|
bool iso_enabled = false;
|
||||||
|
|
||||||
// ISOOUT: Transfer data gathered in previous frame from buffer to RAM
|
// ISOOUT: Transfer data gathered in previous frame from buffer to RAM
|
||||||
if (NRF_USBD->EPOUTEN & USBD_EPOUTEN_ISOOUT_Msk)
|
if (NRF_USBD->EPOUTEN & USBD_EPOUTEN_ISOOUT_Msk) {
|
||||||
{
|
|
||||||
iso_enabled = true;
|
iso_enabled = true;
|
||||||
// Transfer from endpoint to RAM only if data is not corrupted
|
// Transfer from endpoint to RAM only if data is not corrupted
|
||||||
if ((int_status & USBD_INTEN_USBEVENT_Msk) == 0 ||
|
if ((int_status & USBD_INTEN_USBEVENT_Msk) == 0 ||
|
||||||
@ -665,20 +597,17 @@ void dcd_int_handler(uint8_t rhport)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ISOIN: Notify client that data was transferred
|
// ISOIN: Notify client that data was transferred
|
||||||
if (NRF_USBD->EPINEN & USBD_EPINEN_ISOIN_Msk)
|
if (NRF_USBD->EPINEN & USBD_EPINEN_ISOIN_Msk) {
|
||||||
{
|
|
||||||
iso_enabled = true;
|
iso_enabled = true;
|
||||||
|
|
||||||
xfer_td_t* xfer = get_td(EP_ISO_NUM, TUSB_DIR_IN);
|
xfer_td_t* xfer = get_td(EP_ISO_NUM, TUSB_DIR_IN);
|
||||||
if ( xfer->iso_in_transfer_ready )
|
if (xfer->iso_in_transfer_ready) {
|
||||||
{
|
|
||||||
xfer->iso_in_transfer_ready = false;
|
xfer->iso_in_transfer_ready = false;
|
||||||
dcd_event_xfer_complete(0, EP_ISO_NUM | TUSB_DIR_IN_MASK, xfer->actual_len, XFER_RESULT_SUCCESS, true);
|
dcd_event_xfer_complete(0, EP_ISO_NUM | TUSB_DIR_IN_MASK, xfer->actual_len, XFER_RESULT_SUCCESS, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !iso_enabled )
|
if (!iso_enabled) {
|
||||||
{
|
|
||||||
// ISO endpoint is not used, SOF is only enabled one-time for remote wakeup
|
// ISO endpoint is not used, SOF is only enabled one-time for remote wakeup
|
||||||
// so we disable it now
|
// so we disable it now
|
||||||
NRF_USBD->INTENCLR = USBD_INTENSET_SOF_Msk;
|
NRF_USBD->INTENCLR = USBD_INTENSET_SOF_Msk;
|
||||||
@ -687,16 +616,17 @@ void dcd_int_handler(uint8_t rhport)
|
|||||||
dcd_event_bus_signal(0, DCD_EVENT_SOF, true);
|
dcd_event_bus_signal(0, DCD_EVENT_SOF, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( int_status & USBD_INTEN_USBEVENT_Msk )
|
if (int_status & USBD_INTEN_USBEVENT_Msk) {
|
||||||
{
|
|
||||||
TU_LOG(3, "EVENTCAUSE = 0x%04lX\r\n", NRF_USBD->EVENTCAUSE);
|
TU_LOG(3, "EVENTCAUSE = 0x%04lX\r\n", NRF_USBD->EVENTCAUSE);
|
||||||
|
|
||||||
enum { EVT_CAUSE_MASK = USBD_EVENTCAUSE_SUSPEND_Msk | USBD_EVENTCAUSE_RESUME_Msk | USBD_EVENTCAUSE_USBWUALLOWED_Msk | USBD_EVENTCAUSE_ISOOUTCRC_Msk };
|
enum {
|
||||||
|
EVT_CAUSE_MASK = USBD_EVENTCAUSE_SUSPEND_Msk | USBD_EVENTCAUSE_RESUME_Msk | USBD_EVENTCAUSE_USBWUALLOWED_Msk |
|
||||||
|
USBD_EVENTCAUSE_ISOOUTCRC_Msk
|
||||||
|
};
|
||||||
uint32_t const evt_cause = NRF_USBD->EVENTCAUSE & EVT_CAUSE_MASK;
|
uint32_t const evt_cause = NRF_USBD->EVENTCAUSE & EVT_CAUSE_MASK;
|
||||||
NRF_USBD->EVENTCAUSE = evt_cause; // clear interrupt
|
NRF_USBD->EVENTCAUSE = evt_cause; // clear interrupt
|
||||||
|
|
||||||
if ( evt_cause & USBD_EVENTCAUSE_SUSPEND_Msk )
|
if (evt_cause & USBD_EVENTCAUSE_SUSPEND_Msk) {
|
||||||
{
|
|
||||||
// Put controller into low power mode
|
// Put controller into low power mode
|
||||||
// Leave HFXO disable to application, since it may be used by other peripherals
|
// Leave HFXO disable to application, since it may be used by other peripherals
|
||||||
NRF_USBD->LOWPOWER = 1;
|
NRF_USBD->LOWPOWER = 1;
|
||||||
@ -704,8 +634,7 @@ void dcd_int_handler(uint8_t rhport)
|
|||||||
dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true);
|
dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( evt_cause & USBD_EVENTCAUSE_USBWUALLOWED_Msk )
|
if (evt_cause & USBD_EVENTCAUSE_USBWUALLOWED_Msk) {
|
||||||
{
|
|
||||||
// USB is out of low power mode, and wakeup is allowed
|
// USB is out of low power mode, and wakeup is allowed
|
||||||
// Initiate RESUME signal
|
// Initiate RESUME signal
|
||||||
NRF_USBD->DPDMVALUE = USBD_DPDMVALUE_STATE_Resume;
|
NRF_USBD->DPDMVALUE = USBD_DPDMVALUE_STATE_Resume;
|
||||||
@ -717,17 +646,14 @@ void dcd_int_handler(uint8_t rhport)
|
|||||||
NRF_USBD->INTENSET = USBD_INTENSET_SOF_Msk;
|
NRF_USBD->INTENSET = USBD_INTENSET_SOF_Msk;
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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) {
|
||||||
{
|
uint8_t const setup[8] = {
|
||||||
uint8_t const setup[8] =
|
|
||||||
{
|
|
||||||
NRF_USBD->BMREQUESTTYPE, NRF_USBD->BREQUEST, NRF_USBD->WVALUEL, NRF_USBD->WVALUEH,
|
NRF_USBD->BMREQUESTTYPE, NRF_USBD->BREQUEST, NRF_USBD->WVALUEL, NRF_USBD->WVALUEH,
|
||||||
NRF_USBD->WINDEXL, NRF_USBD->WINDEXH, NRF_USBD->WLENGTHL, NRF_USBD->WLENGTHH
|
NRF_USBD->WINDEXL, NRF_USBD->WINDEXH, NRF_USBD->WLENGTHL, NRF_USBD->WLENGTHH
|
||||||
};
|
};
|
||||||
@ -737,14 +663,12 @@ void dcd_int_handler(uint8_t rhport)
|
|||||||
|
|
||||||
if (!(TUSB_REQ_RCPT_DEVICE == request->bmRequestType_bit.recipient &&
|
if (!(TUSB_REQ_RCPT_DEVICE == request->bmRequestType_bit.recipient &&
|
||||||
TUSB_REQ_TYPE_STANDARD == request->bmRequestType_bit.type &&
|
TUSB_REQ_TYPE_STANDARD == request->bmRequestType_bit.type &&
|
||||||
TUSB_REQ_SET_ADDRESS == request->bRequest) )
|
TUSB_REQ_SET_ADDRESS == request->bRequest)) {
|
||||||
{
|
|
||||||
dcd_event_setup_received(0, setup, true);
|
dcd_event_setup_received(0, setup, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( int_status & EDPT_END_ALL_MASK )
|
if (int_status & EDPT_END_ALL_MASK) {
|
||||||
{
|
|
||||||
// DMA complete move data from SRAM <-> Endpoint
|
// DMA complete move data from SRAM <-> Endpoint
|
||||||
// Must before endpoint transfer handling
|
// Must before endpoint transfer handling
|
||||||
edpt_dma_end();
|
edpt_dma_end();
|
||||||
@ -786,10 +710,8 @@ void dcd_int_handler(uint8_t rhport)
|
|||||||
* len if Host decides to sent fewer bytes, it this case transaction is also
|
* len if Host decides to sent fewer bytes, it this case transaction is also
|
||||||
* complete and next transfer is not initiated here like for CBI.
|
* complete and next transfer is not initiated here like for CBI.
|
||||||
*/
|
*/
|
||||||
for(uint8_t epnum=0; epnum<EP_CBI_COUNT+1; epnum++)
|
for (uint8_t epnum = 0; epnum < EP_CBI_COUNT + 1; epnum++) {
|
||||||
{
|
if (tu_bit_test(int_status, USBD_INTEN_ENDEPOUT0_Pos + epnum)) {
|
||||||
if ( tu_bit_test(int_status, USBD_INTEN_ENDEPOUT0_Pos+epnum))
|
|
||||||
{
|
|
||||||
xfer_td_t* xfer = get_td(epnum, TUSB_DIR_OUT);
|
xfer_td_t* xfer = get_td(epnum, TUSB_DIR_OUT);
|
||||||
uint16_t const xact_len = NRF_USBD->EPOUT[epnum].AMOUNT;
|
uint16_t const xact_len = NRF_USBD->EPOUT[epnum].AMOUNT;
|
||||||
|
|
||||||
@ -797,19 +719,15 @@ void dcd_int_handler(uint8_t rhport)
|
|||||||
xfer->actual_len += xact_len;
|
xfer->actual_len += xact_len;
|
||||||
|
|
||||||
// Transfer complete if transaction len < Max Packet Size or total len is transferred
|
// Transfer complete if transaction len < Max Packet Size or total len is transferred
|
||||||
if ( (epnum != EP_ISO_NUM) && (xact_len == xfer->mps) && (xfer->actual_len < xfer->total_len) )
|
if ((epnum != EP_ISO_NUM) && (xact_len == xfer->mps) && (xfer->actual_len < xfer->total_len)) {
|
||||||
{
|
if (epnum == 0) {
|
||||||
if ( epnum == 0 )
|
|
||||||
{
|
|
||||||
// Accept next Control Out packet. TASKS_EP0RCVOUT also require EasyDMA
|
// Accept next Control Out packet. TASKS_EP0RCVOUT also require EasyDMA
|
||||||
edpt_dma_start(&NRF_USBD->TASKS_EP0RCVOUT);
|
edpt_dma_start(&NRF_USBD->TASKS_EP0RCVOUT);
|
||||||
}else
|
} else {
|
||||||
{
|
|
||||||
// nRF auto accept next Bulk/Interrupt OUT packet
|
// nRF auto accept next Bulk/Interrupt OUT packet
|
||||||
// nothing to do
|
// nothing to do
|
||||||
}
|
}
|
||||||
}else
|
} else {
|
||||||
{
|
|
||||||
TU_ASSERT(xfer->started,);
|
TU_ASSERT(xfer->started,);
|
||||||
xfer->total_len = xfer->actual_len;
|
xfer->total_len = xfer->actual_len;
|
||||||
xfer->started = false;
|
xfer->started = false;
|
||||||
@ -823,11 +741,11 @@ void dcd_int_handler(uint8_t rhport)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Endpoint <-> Host ( In & OUT )
|
// Endpoint <-> Host ( In & OUT )
|
||||||
if ( int_status & (USBD_INTEN_EPDATA_Msk | USBD_INTEN_EP0DATADONE_Msk) )
|
if (int_status & (USBD_INTEN_EPDATA_Msk | USBD_INTEN_EP0DATADONE_Msk)) {
|
||||||
{
|
|
||||||
uint32_t data_status = NRF_USBD->EPDATASTATUS;
|
uint32_t data_status = NRF_USBD->EPDATASTATUS;
|
||||||
NRF_USBD->EPDATASTATUS = data_status;
|
NRF_USBD->EPDATASTATUS = data_status;
|
||||||
__ISB(); __DSB();
|
__ISB();
|
||||||
|
__DSB();
|
||||||
|
|
||||||
// EP0DATADONE is set with either Control Out on IN Data
|
// EP0DATADONE is set with either Control Out on IN Data
|
||||||
// Since EPDATASTATUS cannot be used to determine whether it is control OUT or IN.
|
// Since EPDATASTATUS cannot be used to determine whether it is control OUT or IN.
|
||||||
@ -836,22 +754,18 @@ void dcd_int_handler(uint8_t rhport)
|
|||||||
bool const is_control_out = (int_status & USBD_INTEN_EP0DATADONE_Msk) && !(NRF_USBD->BMREQUESTTYPE & TUSB_DIR_IN_MASK);
|
bool const is_control_out = (int_status & USBD_INTEN_EP0DATADONE_Msk) && !(NRF_USBD->BMREQUESTTYPE & TUSB_DIR_IN_MASK);
|
||||||
|
|
||||||
// CBI In: Endpoint -> Host (transaction complete)
|
// CBI In: Endpoint -> Host (transaction complete)
|
||||||
for(uint8_t epnum=0; epnum<EP_CBI_COUNT; epnum++)
|
for (uint8_t epnum = 0; epnum < EP_CBI_COUNT; epnum++) {
|
||||||
{
|
if (tu_bit_test(data_status, epnum) || (epnum == 0 && is_control_in)) {
|
||||||
if ( tu_bit_test(data_status, epnum) || (epnum == 0 && is_control_in) )
|
|
||||||
{
|
|
||||||
xfer_td_t* xfer = get_td(epnum, TUSB_DIR_IN);
|
xfer_td_t* xfer = get_td(epnum, TUSB_DIR_IN);
|
||||||
uint8_t const xact_len = NRF_USBD->EPIN[epnum].AMOUNT;
|
uint8_t const xact_len = NRF_USBD->EPIN[epnum].AMOUNT;
|
||||||
|
|
||||||
xfer->buffer += xact_len;
|
xfer->buffer += xact_len;
|
||||||
xfer->actual_len += xact_len;
|
xfer->actual_len += xact_len;
|
||||||
|
|
||||||
if ( xfer->actual_len < xfer->total_len )
|
if (xfer->actual_len < xfer->total_len) {
|
||||||
{
|
|
||||||
// Start DMA to copy next data packet
|
// Start DMA to copy next data packet
|
||||||
xact_in_dma(epnum);
|
xact_in_dma(epnum);
|
||||||
} else
|
} else {
|
||||||
{
|
|
||||||
// CBI IN complete
|
// CBI IN complete
|
||||||
dcd_event_xfer_complete(0, epnum | TUSB_DIR_IN_MASK, xfer->actual_len, XFER_RESULT_SUCCESS, true);
|
dcd_event_xfer_complete(0, epnum | TUSB_DIR_IN_MASK, xfer->actual_len, XFER_RESULT_SUCCESS, true);
|
||||||
}
|
}
|
||||||
@ -859,17 +773,13 @@ void dcd_int_handler(uint8_t rhport)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CBI OUT: Host -> Endpoint
|
// CBI OUT: Host -> Endpoint
|
||||||
for(uint8_t epnum=0; epnum<EP_CBI_COUNT; epnum++)
|
for (uint8_t epnum = 0; epnum < EP_CBI_COUNT; epnum++) {
|
||||||
{
|
if (tu_bit_test(data_status, 16 + epnum) || (epnum == 0 && is_control_out)) {
|
||||||
if ( tu_bit_test(data_status, 16+epnum) || (epnum == 0 && is_control_out) )
|
|
||||||
{
|
|
||||||
xfer_td_t* xfer = get_td(epnum, TUSB_DIR_OUT);
|
xfer_td_t* xfer = get_td(epnum, TUSB_DIR_OUT);
|
||||||
|
|
||||||
if ( xfer->started && xfer->actual_len < xfer->total_len )
|
if (xfer->started && xfer->actual_len < xfer->total_len) {
|
||||||
{
|
|
||||||
xact_out_dma(epnum);
|
xact_out_dma(epnum);
|
||||||
}else
|
} else {
|
||||||
{
|
|
||||||
// Data overflow !!! Nah, nRF will auto accept next Bulk/Interrupt OUT packet
|
// Data overflow !!! Nah, nRF will auto accept next Bulk/Interrupt OUT packet
|
||||||
// Mark this endpoint with data received
|
// Mark this endpoint with data received
|
||||||
xfer->data_received = true;
|
xfer->data_received = true;
|
||||||
@ -893,27 +803,22 @@ void dcd_int_handler(uint8_t rhport)
|
|||||||
#define SD_MAGIC_NUMBER 0x51B1E5DB
|
#define SD_MAGIC_NUMBER 0x51B1E5DB
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static inline bool is_sd_existed(void)
|
TU_ATTR_ALWAYS_INLINE static inline bool is_sd_existed(void) {
|
||||||
{
|
|
||||||
return *((uint32_t*)(SOFTDEVICE_INFO_STRUCT_ADDRESS+4)) == SD_MAGIC_NUMBER;
|
return *((uint32_t*)(SOFTDEVICE_INFO_STRUCT_ADDRESS+4)) == SD_MAGIC_NUMBER;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if SD is existed and enabled
|
// check if SD is existed and enabled
|
||||||
static inline bool is_sd_enabled(void)
|
TU_ATTR_ALWAYS_INLINE static inline bool is_sd_enabled(void) {
|
||||||
{
|
|
||||||
if ( !is_sd_existed() ) return false;
|
if ( !is_sd_existed() ) return false;
|
||||||
|
|
||||||
uint8_t sd_en = false;
|
uint8_t sd_en = false;
|
||||||
(void) sd_softdevice_is_enabled(&sd_en);
|
(void) sd_softdevice_is_enabled(&sd_en);
|
||||||
return sd_en;
|
return sd_en;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static bool hfclk_running(void)
|
static bool hfclk_running(void) {
|
||||||
{
|
|
||||||
#ifdef SOFTDEVICE_PRESENT
|
#ifdef SOFTDEVICE_PRESENT
|
||||||
if ( is_sd_enabled() )
|
if ( is_sd_enabled() ) {
|
||||||
{
|
|
||||||
uint32_t is_running = 0;
|
uint32_t is_running = 0;
|
||||||
(void) sd_clock_hfclk_is_running(&is_running);
|
(void) sd_clock_hfclk_is_running(&is_running);
|
||||||
return (is_running ? true : false);
|
return (is_running ? true : false);
|
||||||
@ -927,8 +832,7 @@ static bool hfclk_running(void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hfclk_enable(void)
|
static void hfclk_enable(void) {
|
||||||
{
|
|
||||||
#if CFG_TUSB_OS == OPT_OS_MYNEWT
|
#if CFG_TUSB_OS == OPT_OS_MYNEWT
|
||||||
usb_clock_request();
|
usb_clock_request();
|
||||||
return;
|
return;
|
||||||
@ -938,8 +842,7 @@ static void hfclk_enable(void)
|
|||||||
if (hfclk_running()) return;
|
if (hfclk_running()) return;
|
||||||
|
|
||||||
#ifdef SOFTDEVICE_PRESENT
|
#ifdef SOFTDEVICE_PRESENT
|
||||||
if ( is_sd_enabled() )
|
if ( is_sd_enabled() ) {
|
||||||
{
|
|
||||||
(void)sd_clock_hfclk_request();
|
(void)sd_clock_hfclk_request();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -955,16 +858,14 @@ static void hfclk_enable(void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hfclk_disable(void)
|
static void hfclk_disable(void) {
|
||||||
{
|
|
||||||
#if CFG_TUSB_OS == OPT_OS_MYNEWT
|
#if CFG_TUSB_OS == OPT_OS_MYNEWT
|
||||||
usb_clock_release();
|
usb_clock_release();
|
||||||
return;
|
return;
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#ifdef SOFTDEVICE_PRESENT
|
#ifdef SOFTDEVICE_PRESENT
|
||||||
if ( is_sd_enabled() )
|
if ( is_sd_enabled() ) {
|
||||||
{
|
|
||||||
(void)sd_clock_hfclk_release();
|
(void)sd_clock_hfclk_release();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -988,8 +889,7 @@ static void hfclk_disable(void)
|
|||||||
// Therefore this function must be called to handle USB power event by
|
// Therefore this function must be called to handle USB power event by
|
||||||
// - nrfx_power_usbevt_init() : if Softdevice is not used or enabled
|
// - nrfx_power_usbevt_init() : if Softdevice is not used or enabled
|
||||||
// - SoftDevice SOC event : if SD is used and enabled
|
// - SoftDevice SOC event : if SD is used and enabled
|
||||||
void tusb_hal_nrf_power_event (uint32_t event)
|
void tusb_hal_nrf_power_event(uint32_t event) {
|
||||||
{
|
|
||||||
// Value is chosen to be as same as NRFX_POWER_USB_EVT_* in nrfx_power.h
|
// Value is chosen to be as same as NRFX_POWER_USB_EVT_* in nrfx_power.h
|
||||||
enum {
|
enum {
|
||||||
USB_EVT_DETECTED = 0,
|
USB_EVT_DETECTED = 0,
|
||||||
@ -1002,45 +902,36 @@ void tusb_hal_nrf_power_event (uint32_t event)
|
|||||||
TU_LOG(2, "Power USB event: %s\r\n", power_evt_str[event]);
|
TU_LOG(2, "Power USB event: %s\r\n", power_evt_str[event]);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
switch ( event )
|
switch (event) {
|
||||||
{
|
|
||||||
case USB_EVT_DETECTED:
|
case USB_EVT_DETECTED:
|
||||||
if ( !NRF_USBD->ENABLE )
|
if (!NRF_USBD->ENABLE) {
|
||||||
{
|
|
||||||
// Prepare for receiving READY event: disable interrupt since we will blocking wait
|
// Prepare for receiving READY event: disable interrupt since we will blocking wait
|
||||||
NRF_USBD->INTENCLR = USBD_INTEN_USBEVENT_Msk;
|
NRF_USBD->INTENCLR = USBD_INTEN_USBEVENT_Msk;
|
||||||
NRF_USBD->EVENTCAUSE = USBD_EVENTCAUSE_READY_Msk;
|
NRF_USBD->EVENTCAUSE = USBD_EVENTCAUSE_READY_Msk;
|
||||||
__ISB(); __DSB(); // for sync
|
__ISB();
|
||||||
|
__DSB(); // for sync
|
||||||
|
|
||||||
#ifdef NRF52_SERIES // NRF53 does not need this errata
|
#ifdef NRF52_SERIES // NRF53 does not need this errata
|
||||||
// ERRATA 171, 187, 166
|
// ERRATA 171, 187, 166
|
||||||
if ( nrfx_usbd_errata_187() )
|
if (nrfx_usbd_errata_187()) {
|
||||||
{
|
|
||||||
// CRITICAL_REGION_ENTER();
|
// CRITICAL_REGION_ENTER();
|
||||||
if ( *((volatile uint32_t *) (0x4006EC00)) == 0x00000000 )
|
if (*((volatile uint32_t*) (0x4006EC00)) == 0x00000000) {
|
||||||
{
|
|
||||||
*((volatile uint32_t*) (0x4006EC00)) = 0x00009375;
|
*((volatile uint32_t*) (0x4006EC00)) = 0x00009375;
|
||||||
*((volatile uint32_t*) (0x4006ED14)) = 0x00000003;
|
*((volatile uint32_t*) (0x4006ED14)) = 0x00000003;
|
||||||
*((volatile uint32_t*) (0x4006EC00)) = 0x00009375;
|
*((volatile uint32_t*) (0x4006EC00)) = 0x00009375;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
*((volatile uint32_t*) (0x4006ED14)) = 0x00000003;
|
*((volatile uint32_t*) (0x4006ED14)) = 0x00000003;
|
||||||
}
|
}
|
||||||
// CRITICAL_REGION_EXIT();
|
// CRITICAL_REGION_EXIT();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( nrfx_usbd_errata_171() )
|
if (nrfx_usbd_errata_171()) {
|
||||||
{
|
|
||||||
// CRITICAL_REGION_ENTER();
|
// CRITICAL_REGION_ENTER();
|
||||||
if ( *((volatile uint32_t *) (0x4006EC00)) == 0x00000000 )
|
if (*((volatile uint32_t*) (0x4006EC00)) == 0x00000000) {
|
||||||
{
|
|
||||||
*((volatile uint32_t*) (0x4006EC00)) = 0x00009375;
|
*((volatile uint32_t*) (0x4006EC00)) = 0x00009375;
|
||||||
*((volatile uint32_t*) (0x4006EC14)) = 0x000000C0;
|
*((volatile uint32_t*) (0x4006EC14)) = 0x000000C0;
|
||||||
*((volatile uint32_t*) (0x4006EC00)) = 0x00009375;
|
*((volatile uint32_t*) (0x4006EC00)) = 0x00009375;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
*((volatile uint32_t*) (0x4006EC14)) = 0x000000C0;
|
*((volatile uint32_t*) (0x4006EC14)) = 0x000000C0;
|
||||||
}
|
}
|
||||||
// CRITICAL_REGION_EXIT();
|
// CRITICAL_REGION_EXIT();
|
||||||
@ -1049,7 +940,8 @@ void tusb_hal_nrf_power_event (uint32_t event)
|
|||||||
|
|
||||||
// Enable the peripheral (will cause Ready event)
|
// Enable the peripheral (will cause Ready event)
|
||||||
NRF_USBD->ENABLE = 1;
|
NRF_USBD->ENABLE = 1;
|
||||||
__ISB(); __DSB(); // for sync
|
__ISB();
|
||||||
|
__DSB(); // for sync
|
||||||
|
|
||||||
// Enable HFCLK
|
// Enable HFCLK
|
||||||
hfclk_enable();
|
hfclk_enable();
|
||||||
@ -1065,48 +957,41 @@ void tusb_hal_nrf_power_event (uint32_t event)
|
|||||||
while (!(USBD_EVENTCAUSE_READY_Msk & NRF_USBD->EVENTCAUSE)) {}
|
while (!(USBD_EVENTCAUSE_READY_Msk & NRF_USBD->EVENTCAUSE)) {}
|
||||||
|
|
||||||
NRF_USBD->EVENTCAUSE = USBD_EVENTCAUSE_READY_Msk;
|
NRF_USBD->EVENTCAUSE = USBD_EVENTCAUSE_READY_Msk;
|
||||||
__ISB(); __DSB(); // for sync
|
__ISB();
|
||||||
|
__DSB(); // for sync
|
||||||
|
|
||||||
#ifdef NRF52_SERIES
|
#ifdef NRF52_SERIES
|
||||||
if ( nrfx_usbd_errata_171() )
|
if (nrfx_usbd_errata_171()) {
|
||||||
{
|
|
||||||
// CRITICAL_REGION_ENTER();
|
// CRITICAL_REGION_ENTER();
|
||||||
if ( *((volatile uint32_t *) (0x4006EC00)) == 0x00000000 )
|
if (*((volatile uint32_t*) (0x4006EC00)) == 0x00000000) {
|
||||||
{
|
|
||||||
*((volatile uint32_t*) (0x4006EC00)) = 0x00009375;
|
*((volatile uint32_t*) (0x4006EC00)) = 0x00009375;
|
||||||
*((volatile uint32_t*) (0x4006EC14)) = 0x00000000;
|
*((volatile uint32_t*) (0x4006EC14)) = 0x00000000;
|
||||||
*((volatile uint32_t*) (0x4006EC00)) = 0x00009375;
|
*((volatile uint32_t*) (0x4006EC00)) = 0x00009375;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
*((volatile uint32_t*) (0x4006EC14)) = 0x00000000;
|
*((volatile uint32_t*) (0x4006EC14)) = 0x00000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
// CRITICAL_REGION_EXIT();
|
// CRITICAL_REGION_EXIT();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( nrfx_usbd_errata_187() )
|
if (nrfx_usbd_errata_187()) {
|
||||||
{
|
|
||||||
// CRITICAL_REGION_ENTER();
|
// CRITICAL_REGION_ENTER();
|
||||||
if ( *((volatile uint32_t *) (0x4006EC00)) == 0x00000000 )
|
if (*((volatile uint32_t*) (0x4006EC00)) == 0x00000000) {
|
||||||
{
|
|
||||||
*((volatile uint32_t*) (0x4006EC00)) = 0x00009375;
|
*((volatile uint32_t*) (0x4006EC00)) = 0x00009375;
|
||||||
*((volatile uint32_t*) (0x4006ED14)) = 0x00000000;
|
*((volatile uint32_t*) (0x4006ED14)) = 0x00000000;
|
||||||
*((volatile uint32_t*) (0x4006EC00)) = 0x00009375;
|
*((volatile uint32_t*) (0x4006EC00)) = 0x00009375;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
*((volatile uint32_t*) (0x4006ED14)) = 0x00000000;
|
*((volatile uint32_t*) (0x4006ED14)) = 0x00000000;
|
||||||
}
|
}
|
||||||
// CRITICAL_REGION_EXIT();
|
// CRITICAL_REGION_EXIT();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( nrfx_usbd_errata_166() )
|
if (nrfx_usbd_errata_166()) {
|
||||||
{
|
|
||||||
*((volatile uint32_t*) (NRF_USBD_BASE + 0x800)) = 0x7E3;
|
*((volatile uint32_t*) (NRF_USBD_BASE + 0x800)) = 0x7E3;
|
||||||
*((volatile uint32_t*) (NRF_USBD_BASE + 0x804)) = 0x40;
|
*((volatile uint32_t*) (NRF_USBD_BASE + 0x804)) = 0x40;
|
||||||
|
|
||||||
__ISB(); __DSB();
|
__ISB();
|
||||||
|
__DSB();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1122,8 +1007,7 @@ void tusb_hal_nrf_power_event (uint32_t event)
|
|||||||
// Don't enable USBD interrupt yet, if dcd_init() did not finish yet
|
// Don't enable USBD interrupt yet, if dcd_init() did not finish yet
|
||||||
// Interrupt will be enabled by tud_init(), when USB stack is ready
|
// Interrupt will be enabled by tud_init(), when USB stack is ready
|
||||||
// to handle interrupts.
|
// to handle interrupts.
|
||||||
if (tud_inited())
|
if (tud_inited()) {
|
||||||
{
|
|
||||||
NVIC_EnableIRQ(USBD_IRQn);
|
NVIC_EnableIRQ(USBD_IRQn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1132,17 +1016,18 @@ void tusb_hal_nrf_power_event (uint32_t event)
|
|||||||
|
|
||||||
// Enable pull up
|
// Enable pull up
|
||||||
NRF_USBD->USBPULLUP = 1;
|
NRF_USBD->USBPULLUP = 1;
|
||||||
__ISB(); __DSB(); // for sync
|
__ISB();
|
||||||
|
__DSB(); // for sync
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case USB_EVT_REMOVED:
|
case USB_EVT_REMOVED:
|
||||||
if ( NRF_USBD->ENABLE )
|
if (NRF_USBD->ENABLE) {
|
||||||
{
|
|
||||||
// Abort all transfers
|
// Abort all transfers
|
||||||
|
|
||||||
// Disable pull up
|
// Disable pull up
|
||||||
NRF_USBD->USBPULLUP = 0;
|
NRF_USBD->USBPULLUP = 0;
|
||||||
__ISB(); __DSB(); // for sync
|
__ISB();
|
||||||
|
__DSB(); // for sync
|
||||||
|
|
||||||
// Disable Interrupt
|
// Disable Interrupt
|
||||||
NVIC_DisableIRQ(USBD_IRQn);
|
NVIC_DisableIRQ(USBD_IRQn);
|
||||||
@ -1151,7 +1036,8 @@ void tusb_hal_nrf_power_event (uint32_t event)
|
|||||||
NRF_USBD->INTENCLR = NRF_USBD->INTEN;
|
NRF_USBD->INTENCLR = NRF_USBD->INTEN;
|
||||||
|
|
||||||
NRF_USBD->ENABLE = 0;
|
NRF_USBD->ENABLE = 0;
|
||||||
__ISB(); __DSB(); // for sync
|
__ISB();
|
||||||
|
__DSB(); // for sync
|
||||||
|
|
||||||
hfclk_disable();
|
hfclk_disable();
|
||||||
|
|
||||||
@ -1159,7 +1045,8 @@ void tusb_hal_nrf_power_event (uint32_t event)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: break;
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user