got In transfer working, able to get 1st device descriptor and set address
This commit is contained in:
@@ -48,7 +48,7 @@ else
|
|||||||
SRC_C += \
|
SRC_C += \
|
||||||
src/portable/synopsys/dwc2/dcd_dwc2.c \
|
src/portable/synopsys/dwc2/dcd_dwc2.c \
|
||||||
src/portable/synopsys/dwc2/hcd_dwc2.c \
|
src/portable/synopsys/dwc2/hcd_dwc2.c \
|
||||||
src/portable/synopsys/dwc2/dwc2_common.c \
|
src/portable/synopsys/dwc2/dwc2_common.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
INC += \
|
INC += \
|
||||||
|
@@ -445,8 +445,11 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
|
|||||||
// Enable required interrupts
|
// Enable required interrupts
|
||||||
dwc2->gintmsk |= GINTMSK_OTGINT | GINTMSK_USBSUSPM | GINTMSK_USBRST | GINTMSK_ENUMDNEM | GINTMSK_WUIM;
|
dwc2->gintmsk |= GINTMSK_OTGINT | GINTMSK_USBSUSPM | GINTMSK_USBRST | GINTMSK_ENUMDNEM | GINTMSK_WUIM;
|
||||||
|
|
||||||
// Enable global interrupt
|
// TX FIFO empty level for interrupt is complete empty
|
||||||
dwc2->gahbcfg |= GAHBCFG_GINT;
|
uint32_t gahbcfg = dwc2->gahbcfg;
|
||||||
|
gahbcfg |= GAHBCFG_TX_FIFO_EPMTY_LVL;
|
||||||
|
gahbcfg |= GAHBCFG_GINT; // Enable global interrupt
|
||||||
|
dwc2->gahbcfg = gahbcfg;
|
||||||
|
|
||||||
dcd_connect(rhport);
|
dcd_connect(rhport);
|
||||||
return true;
|
return true;
|
||||||
@@ -671,16 +674,15 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) {
|
|||||||
// Process shared receive FIFO, this interrupt is only used in Slave mode
|
// Process shared receive FIFO, this interrupt is only used in Slave mode
|
||||||
static void handle_rxflvl_irq(uint8_t rhport) {
|
static void handle_rxflvl_irq(uint8_t rhport) {
|
||||||
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
|
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
|
||||||
volatile uint32_t const* rx_fifo = dwc2->fifo[0];
|
const volatile uint32_t* rx_fifo = dwc2->fifo[0];
|
||||||
|
|
||||||
// Pop control word off FIFO
|
// Pop control word off FIFO
|
||||||
uint32_t const grxstsp = dwc2->grxstsp;
|
const dwc2_grxstsp_t grxstsp_bm = dwc2->grxstsp_bm;
|
||||||
uint8_t const pktsts = (grxstsp & GRXSTSP_PKTSTS_Msk) >> GRXSTSP_PKTSTS_Pos;
|
const uint8_t epnum = grxstsp_bm.ep_ch_num;
|
||||||
uint8_t const epnum = (grxstsp & GRXSTSP_EPNUM_Msk) >> GRXSTSP_EPNUM_Pos;
|
const uint16_t byte_count = grxstsp_bm.byte_count;
|
||||||
uint16_t const bcnt = (grxstsp & GRXSTSP_BCNT_Msk) >> GRXSTSP_BCNT_Pos;
|
|
||||||
dwc2_epout_t* epout = &dwc2->epout[epnum];
|
dwc2_epout_t* epout = &dwc2->epout[epnum];
|
||||||
|
|
||||||
switch (pktsts) {
|
switch (grxstsp_bm.packet_status) {
|
||||||
// Global OUT NAK: do nothing
|
// Global OUT NAK: do nothing
|
||||||
case GRXSTS_PKTSTS_GLOBALOUTNAK:
|
case GRXSTS_PKTSTS_GLOBALOUTNAK:
|
||||||
break;
|
break;
|
||||||
@@ -705,18 +707,18 @@ static void handle_rxflvl_irq(uint8_t rhport) {
|
|||||||
// Read packet off RxFIFO
|
// Read packet off RxFIFO
|
||||||
if (xfer->ff) {
|
if (xfer->ff) {
|
||||||
// Ring buffer
|
// Ring buffer
|
||||||
tu_fifo_write_n_const_addr_full_words(xfer->ff, (const void*) (uintptr_t) rx_fifo, bcnt);
|
tu_fifo_write_n_const_addr_full_words(xfer->ff, (const void*) (uintptr_t) rx_fifo, byte_count);
|
||||||
} else {
|
} else {
|
||||||
// Linear buffer
|
// Linear buffer
|
||||||
dfifo_read_packet(dwc2, xfer->buffer, bcnt);
|
dfifo_read_packet(dwc2, xfer->buffer, byte_count);
|
||||||
|
|
||||||
// Increment pointer to xfer data
|
// Increment pointer to xfer data
|
||||||
xfer->buffer += bcnt;
|
xfer->buffer += byte_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Truncate transfer length in case of short packet
|
// short packet, minus remaining bytes (xfer_size)
|
||||||
if (bcnt < xfer->max_size) {
|
if (byte_count < xfer->max_size) {
|
||||||
xfer->total_len -= (epout->doeptsiz & DOEPTSIZ_XFRSIZ_Msk) >> DOEPTSIZ_XFRSIZ_Pos;
|
xfer->total_len -= epout->doeptsiz_bm.xfer_size;
|
||||||
if (epnum == 0) {
|
if (epnum == 0) {
|
||||||
xfer->total_len -= ep0_pending[TUSB_DIR_OUT];
|
xfer->total_len -= ep0_pending[TUSB_DIR_OUT];
|
||||||
ep0_pending[TUSB_DIR_OUT] = 0;
|
ep0_pending[TUSB_DIR_OUT] = 0;
|
||||||
|
@@ -242,9 +242,6 @@ bool dwc2_core_init(uint8_t rhport, bool is_highspeed, bool is_dma) {
|
|||||||
dwc2->gintmsk |= GINTMSK_RXFLVLM;
|
dwc2->gintmsk |= GINTMSK_RXFLVLM;
|
||||||
}
|
}
|
||||||
|
|
||||||
// (non-periodic) TX FIFO empty level for interrupt is complete empty
|
|
||||||
dwc2->gahbcfg |= GAHBCFG_TX_FIFO_EPMTY_LVL;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -145,6 +145,21 @@ enum {
|
|||||||
HCTSIZ_PID_SETUP = 3,
|
HCTSIZ_PID_SETUP = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
GRXSTS_PKTSTS_GLOBALOUTNAK = 1,
|
||||||
|
GRXSTS_PKTSTS_OUTRX = 2,
|
||||||
|
GRXSTS_PKTSTS_OUTDONE = 3,
|
||||||
|
GRXSTS_PKTSTS_SETUPDONE = 4,
|
||||||
|
GRXSTS_PKTSTS_SETUPRX = 6
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
GRXSTS_PKTSTS_HOST_IN_RECEIVED = 2,
|
||||||
|
GRXSTS_PKTSTS_HOST_IN_XFER_COMPL = 3,
|
||||||
|
GRXSTS_PKTSTS_HOST_DATATOGGLE_ERR = 5,
|
||||||
|
GRXSTS_PKTSTS_HOST_CHANNEL_HALTED = 7
|
||||||
|
};
|
||||||
|
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
// Common Register Bitfield
|
// Common Register Bitfield
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
@@ -263,6 +278,17 @@ typedef struct TU_ATTR_PACKED {
|
|||||||
} dwc2_grstctl_t;
|
} dwc2_grstctl_t;
|
||||||
TU_VERIFY_STATIC(sizeof(dwc2_grstctl_t) == 4, "incorrect size");
|
TU_VERIFY_STATIC(sizeof(dwc2_grstctl_t) == 4, "incorrect size");
|
||||||
|
|
||||||
|
typedef struct TU_ATTR_PACKED {
|
||||||
|
uint32_t ep_ch_num : 4; // 0..3 Endpoint/Channel Number
|
||||||
|
uint32_t byte_count :11; // 4..14 Byte Count
|
||||||
|
uint32_t dpid : 2; // 15..16 Data PID
|
||||||
|
uint32_t packet_status : 4; // 17..20 Packet Status
|
||||||
|
uint32_t frame_number : 4; // 21..24 Frame Number
|
||||||
|
uint32_t rsv25_31 : 7; // 25..31 Reserved
|
||||||
|
} dwc2_grxstsp_t;
|
||||||
|
TU_VERIFY_STATIC(sizeof(dwc2_grxstsp_t) == 4, "incorrect size");
|
||||||
|
|
||||||
|
// Hardware Configuration
|
||||||
typedef struct TU_ATTR_PACKED {
|
typedef struct TU_ATTR_PACKED {
|
||||||
uint32_t op_mode : 3; // 0..2 HNP/SRP Host/Device/OTG mode
|
uint32_t op_mode : 3; // 0..2 HNP/SRP Host/Device/OTG mode
|
||||||
uint32_t arch : 2; // 3..4 Slave/External/Internal DMA
|
uint32_t arch : 2; // 3..4 Slave/External/Internal DMA
|
||||||
@@ -496,7 +522,10 @@ typedef struct {
|
|||||||
volatile uint32_t gintsts; // 014 Interrupt
|
volatile uint32_t gintsts; // 014 Interrupt
|
||||||
volatile uint32_t gintmsk; // 018 Interrupt Mask
|
volatile uint32_t gintmsk; // 018 Interrupt Mask
|
||||||
volatile uint32_t grxstsr; // 01c Receive Status Debug Read
|
volatile uint32_t grxstsr; // 01c Receive Status Debug Read
|
||||||
|
union {
|
||||||
volatile uint32_t grxstsp; // 020 Receive Status Read/Pop
|
volatile uint32_t grxstsp; // 020 Receive Status Read/Pop
|
||||||
|
volatile dwc2_grxstsp_t grxstsp_bm;
|
||||||
|
};
|
||||||
volatile uint32_t grxfsiz; // 024 Receive FIFO Size
|
volatile uint32_t grxfsiz; // 024 Receive FIFO Size
|
||||||
union {
|
union {
|
||||||
volatile uint32_t dieptxf0; // 028 EP0 Tx FIFO Size
|
volatile uint32_t dieptxf0; // 028 EP0 Tx FIFO Size
|
||||||
@@ -1236,17 +1265,6 @@ TU_VERIFY_STATIC(offsetof(dwc2_regs_t, fifo ) == 0x1000, "incorrect size");
|
|||||||
#define GRXSTSP_PKTSTS_Msk (0xFUL << GRXSTSP_PKTSTS_Pos) // 0x001E0000
|
#define GRXSTSP_PKTSTS_Msk (0xFUL << GRXSTSP_PKTSTS_Pos) // 0x001E0000
|
||||||
#define GRXSTSP_PKTSTS GRXSTSP_PKTSTS_Msk // OUT EP interrupt mask bits
|
#define GRXSTSP_PKTSTS GRXSTSP_PKTSTS_Msk // OUT EP interrupt mask bits
|
||||||
|
|
||||||
#define GRXSTS_PKTSTS_GLOBALOUTNAK 1
|
|
||||||
#define GRXSTS_PKTSTS_OUTRX 2
|
|
||||||
#define GRXSTS_PKTSTS_HCHIN 2
|
|
||||||
#define GRXSTS_PKTSTS_OUTDONE 3
|
|
||||||
#define GRXSTS_PKTSTS_HCHIN_XFER_COMP 3
|
|
||||||
#define GRXSTS_PKTSTS_SETUPDONE 4
|
|
||||||
#define GRXSTS_PKTSTS_DATATOGGLEERR 5
|
|
||||||
#define GRXSTS_PKTSTS_SETUPRX 6
|
|
||||||
#define GRXSTS_PKTSTS_HCHHALTED 7
|
|
||||||
|
|
||||||
|
|
||||||
/******************** Bit definition for DAINTMSK register ********************/
|
/******************** Bit definition for DAINTMSK register ********************/
|
||||||
#define DAINTMSK_IEPM_Pos (0U)
|
#define DAINTMSK_IEPM_Pos (0U)
|
||||||
#define DAINTMSK_IEPM_Msk (0xFFFFUL << DAINTMSK_IEPM_Pos) // 0x0000FFFF
|
#define DAINTMSK_IEPM_Msk (0xFFFFUL << DAINTMSK_IEPM_Pos) // 0x0000FFFF
|
||||||
|
@@ -54,7 +54,7 @@ typedef struct {
|
|||||||
dwc2_channel_split_t hcsplt_bm;
|
dwc2_channel_split_t hcsplt_bm;
|
||||||
};
|
};
|
||||||
|
|
||||||
uint8_t* buf;
|
uint8_t* buffer;
|
||||||
uint16_t total_len;
|
uint16_t total_len;
|
||||||
uint8_t next_data_toggle;
|
uint8_t next_data_toggle;
|
||||||
bool pending_tx;
|
bool pending_tx;
|
||||||
@@ -218,7 +218,7 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
|
|||||||
dwc2->hprt = HPRT_POWER; // turn on VBUS
|
dwc2->hprt = HPRT_POWER; // turn on VBUS
|
||||||
|
|
||||||
// Enable required interrupts
|
// Enable required interrupts
|
||||||
dwc2->gintmsk |= GINTMSK_OTGINT | GINTSTS_CONIDSTSCHNG | GINTMSK_PRTIM ; // | GINTMSK_WUIM;
|
dwc2->gintmsk |= GINTSTS_OTGINT | GINTSTS_CONIDSTSCHNG | GINTSTS_HPRTINT | GINTSTS_HCINT;
|
||||||
|
|
||||||
// NPTX can hold at least 2 packet, change interrupt level to half-empty
|
// NPTX can hold at least 2 packet, change interrupt level to half-empty
|
||||||
uint32_t gahbcfg = dwc2->gahbcfg & ~GAHBCFG_TX_FIFO_EPMTY_LVL;
|
uint32_t gahbcfg = dwc2->gahbcfg & ~GAHBCFG_TX_FIFO_EPMTY_LVL;
|
||||||
@@ -354,6 +354,11 @@ TU_ATTR_ALWAYS_INLINE static inline uint8_t find_opened_pipe(uint8_t dev_addr, u
|
|||||||
return TUSB_INDEX_INVALID_8;
|
return TUSB_INDEX_INVALID_8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TU_ATTR_ALWAYS_INLINE static inline uint8_t find_opened_pipe_by_channel(const dwc2_channel_t* channel) {
|
||||||
|
const dwc2_channel_char_t hcchar_bm = channel->hcchar_bm;
|
||||||
|
return find_opened_pipe(hcchar_bm.dev_addr, hcchar_bm.ep_num, hcchar_bm.ep_dir);
|
||||||
|
}
|
||||||
|
|
||||||
void schedule_out_packet(dwc2_regs_t* dwc2, uint8_t pipe_id, uint8_t ch_id) {
|
void schedule_out_packet(dwc2_regs_t* dwc2, uint8_t pipe_id, uint8_t ch_id) {
|
||||||
// To prevent conflict with other channel, we will enable periodic/non-periodic FIFO empty interrupt accordingly.
|
// To prevent conflict with other channel, we will enable periodic/non-periodic FIFO empty interrupt accordingly.
|
||||||
// And write packet in the interrupt handler
|
// And write packet in the interrupt handler
|
||||||
@@ -382,8 +387,12 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *
|
|||||||
dwc2->haintmsk |= TU_BIT(ch_id);
|
dwc2->haintmsk |= TU_BIT(ch_id);
|
||||||
|
|
||||||
dwc2_channel_t* channel = &dwc2->channel[ch_id];
|
dwc2_channel_t* channel = &dwc2->channel[ch_id];
|
||||||
channel->hcintmsk = HCINT_XFER_COMPLETE | HCINT_CHANNEL_HALTED | HCINT_STALL |
|
uint32_t hcintmsk = HCINT_XFER_COMPLETE | HCINT_CHANNEL_HALTED | HCINT_STALL |
|
||||||
HCINT_AHB_ERR | HCINT_XACT_ERR | HCINT_BABBLE_ERR | HCINT_DATATOGGLE_ERR;
|
HCINT_AHB_ERR | HCINT_XACT_ERR | HCINT_BABBLE_ERR | HCINT_DATATOGGLE_ERR;
|
||||||
|
if (ep_dir == TUSB_DIR_IN) {
|
||||||
|
hcintmsk |= HCINT_NAK;
|
||||||
|
}
|
||||||
|
channel->hcintmsk = hcintmsk;
|
||||||
|
|
||||||
uint16_t packet_count = tu_div_ceil(buflen, hcchar_bm->ep_size);
|
uint16_t packet_count = tu_div_ceil(buflen, hcchar_bm->ep_size);
|
||||||
if (packet_count == 0) {
|
if (packet_count == 0) {
|
||||||
@@ -405,21 +414,24 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *
|
|||||||
hcchar_bm->ep_dir = ep_dir; // control endpoint can switch direction
|
hcchar_bm->ep_dir = ep_dir; // control endpoint can switch direction
|
||||||
channel->hcchar = pipe->hcchar & ~HCCHAR_CHENA; // restore hcchar but don't enable yet
|
channel->hcchar = pipe->hcchar & ~HCCHAR_CHENA; // restore hcchar but don't enable yet
|
||||||
|
|
||||||
|
pipe->buffer = buffer;
|
||||||
|
pipe->total_len = buflen;
|
||||||
|
|
||||||
if (dma_host_enabled(dwc2)) {
|
if (dma_host_enabled(dwc2)) {
|
||||||
channel->hcdma = (uint32_t) buffer;
|
channel->hcdma = (uint32_t) buffer;
|
||||||
} else {
|
} else {
|
||||||
|
// enable channel for:
|
||||||
|
// - OUT endpoint: it will enable corresponding FIFO channel
|
||||||
|
// - IN endpoint: it will write an IN request to the Non-periodic Request Queue, this will have dwc2 trying to send
|
||||||
|
// IN Token. If we got NAK, we have to re-enable the channel again in the interrupt. Due to the way usbh stack only
|
||||||
|
// call hcd_edpt_xfer() once, we will need to manage de-allocate/re-allocate IN channel dynamically.
|
||||||
|
channel->hcchar |= HCCHAR_CHENA;
|
||||||
|
|
||||||
if (ep_dir == TUSB_DIR_IN) {
|
if (ep_dir == TUSB_DIR_IN) {
|
||||||
TU_ASSERT(false); // not yet support
|
|
||||||
} else {
|
} else {
|
||||||
pipe->buf = buffer;
|
if (buflen > 0) {
|
||||||
pipe->total_len = buflen;
|
|
||||||
|
|
||||||
channel->hcchar |= HCCHAR_CHENA; // enable channel before writing to FIFO
|
|
||||||
|
|
||||||
if (ep_dir == TUSB_DIR_OUT && buflen > 0) {
|
|
||||||
schedule_out_packet(dwc2, pipe_id, ch_id);
|
schedule_out_packet(dwc2, pipe_id, ch_id);
|
||||||
} else {
|
|
||||||
TU_ASSERT(false); // not yet support
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -460,20 +472,50 @@ bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) {
|
|||||||
// HCD Event Handler
|
// HCD Event Handler
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
#if 1
|
|
||||||
static void handle_rxflvl_irq(uint8_t rhport) {
|
static void handle_rxflvl_irq(uint8_t rhport) {
|
||||||
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
|
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
|
||||||
// volatile uint32_t const* rx_fifo = dwc2->fifo[0];
|
|
||||||
|
|
||||||
// Pop control word off FIFO
|
// Pop control word off FIFO
|
||||||
uint32_t const grxstsp = dwc2->grxstsp;
|
const dwc2_grxstsp_t grxstsp_bm = dwc2->grxstsp_bm;
|
||||||
(void) grxstsp;
|
const uint8_t ch_id = grxstsp_bm.ep_ch_num;
|
||||||
// uint8_t const pktsts = (grxstsp & GRXSTSP_PKTSTS_Msk) >> GRXSTSP_PKTSTS_Pos;
|
dwc2_channel_t* channel = &dwc2->channel[ch_id];
|
||||||
// uint8_t const epnum = (grxstsp & GRXSTSP_EPNUM_Msk) >> GRXSTSP_EPNUM_Pos;
|
|
||||||
// uint16_t const bcnt = (grxstsp & GRXSTSP_BCNT_Msk) >> GRXSTSP_BCNT_Pos;
|
switch (grxstsp_bm.packet_status) {
|
||||||
// dwc2_epout_t* epout = &dwc2->epout[epnum];
|
case GRXSTS_PKTSTS_HOST_IN_RECEIVED: {
|
||||||
|
// In packet received
|
||||||
|
const uint16_t byte_count = grxstsp_bm.byte_count;
|
||||||
|
const uint8_t pipe_id = find_opened_pipe_by_channel(channel);
|
||||||
|
TU_VERIFY(pipe_id < CFG_TUH_DWC2_ENDPOINT_MAX, );
|
||||||
|
hcd_pipe_t* pipe = &_hcd_data.pipe[pipe_id];
|
||||||
|
|
||||||
|
dfifo_read_packet(dwc2, pipe->buffer, byte_count);
|
||||||
|
pipe->buffer += byte_count;
|
||||||
|
|
||||||
|
// short packet, minus remaining bytes (xfer_size)
|
||||||
|
if (byte_count < channel->hctsiz_bm.xfer_size) {
|
||||||
|
pipe->total_len -= channel->hctsiz_bm.xfer_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case GRXSTS_PKTSTS_HOST_IN_XFER_COMPL:
|
||||||
|
// In transfer complete: After this entry is popped from the receive FIFO, dwc2 asserts a Transfer Completed
|
||||||
|
// interrupt --> handle_channel_irq()
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GRXSTS_PKTSTS_HOST_DATATOGGLE_ERR:
|
||||||
|
TU_ASSERT(0, ); // maybe try to change DToggle
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GRXSTS_PKTSTS_HOST_CHANNEL_HALTED:
|
||||||
|
// triggered when channel.hcchar_bm.disable is set
|
||||||
|
// TODO handle later
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: break; // ignore other status
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Handle Host Port interrupt, possible source are:
|
/* Handle Host Port interrupt, possible source are:
|
||||||
- Connection Detection
|
- Connection Detection
|
||||||
@@ -548,6 +590,11 @@ void handle_channel_irq(uint8_t rhport, bool in_isr) {
|
|||||||
uint32_t hcint = channel->hcint;
|
uint32_t hcint = channel->hcint;
|
||||||
hcint &= channel->hcintmsk;
|
hcint &= channel->hcintmsk;
|
||||||
|
|
||||||
|
if (hcint & HCINT_NAK) {
|
||||||
|
// NAK received, re-enable channel. Check if request queue is available
|
||||||
|
channel->hcchar |= HCCHAR_CHENA;
|
||||||
|
} else {
|
||||||
|
// transfer result interrupt
|
||||||
xfer_result_t result = XFER_RESULT_FAILED;
|
xfer_result_t result = XFER_RESULT_FAILED;
|
||||||
if (hcint & HCINT_XFER_COMPLETE) {
|
if (hcint & HCINT_XFER_COMPLETE) {
|
||||||
result = XFER_RESULT_SUCCESS;
|
result = XFER_RESULT_SUCCESS;
|
||||||
@@ -563,11 +610,12 @@ void handle_channel_irq(uint8_t rhport, bool in_isr) {
|
|||||||
const uint8_t ep_addr = tu_edpt_addr(channel->hcchar_bm.ep_num, channel->hcchar_bm.ep_dir);
|
const uint8_t ep_addr = tu_edpt_addr(channel->hcchar_bm.ep_num, channel->hcchar_bm.ep_dir);
|
||||||
hcd_event_xfer_complete(channel->hcchar_bm.dev_addr, ep_addr, 0, result, in_isr);
|
hcd_event_xfer_complete(channel->hcchar_bm.dev_addr, ep_addr, 0, result, in_isr);
|
||||||
|
|
||||||
channel->hcint = hcint; // clear all interrupt flags
|
|
||||||
|
|
||||||
// de-allocate channel by clearing haintmsk
|
// de-allocate channel by clearing haintmsk
|
||||||
dwc2->haintmsk &= ~TU_BIT(ch_id);
|
dwc2->haintmsk &= ~TU_BIT(ch_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
channel->hcint = hcint; // clear all interrupt flags
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -581,7 +629,7 @@ bool handle_txfifo_empty(dwc2_regs_t* dwc2, bool is_periodic) {
|
|||||||
dwc2_channel_t* channel = &dwc2->channel[ch_id];
|
dwc2_channel_t* channel = &dwc2->channel[ch_id];
|
||||||
const dwc2_channel_char_t hcchar_bm = channel->hcchar_bm;
|
const dwc2_channel_char_t hcchar_bm = channel->hcchar_bm;
|
||||||
if (hcchar_bm.ep_dir == TUSB_DIR_OUT) {
|
if (hcchar_bm.ep_dir == TUSB_DIR_OUT) {
|
||||||
uint8_t pipe_id = find_opened_pipe(hcchar_bm.dev_addr, hcchar_bm.ep_num, TUSB_DIR_OUT);
|
uint8_t pipe_id = find_opened_pipe_by_channel(channel);
|
||||||
if (pipe_id < CFG_TUH_DWC2_ENDPOINT_MAX) {
|
if (pipe_id < CFG_TUH_DWC2_ENDPOINT_MAX) {
|
||||||
hcd_pipe_t* pipe = &_hcd_data.pipe[pipe_id];
|
hcd_pipe_t* pipe = &_hcd_data.pipe[pipe_id];
|
||||||
if (pipe->pending_tx) {
|
if (pipe->pending_tx) {
|
||||||
@@ -595,8 +643,8 @@ bool handle_txfifo_empty(dwc2_regs_t* dwc2, bool is_periodic) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
dfifo_write_packet(dwc2, ch_id, pipe->buf, packet_bytes);
|
dfifo_write_packet(dwc2, ch_id, pipe->buffer, packet_bytes);
|
||||||
pipe->buf += packet_bytes;
|
pipe->buffer += packet_bytes;
|
||||||
|
|
||||||
if (channel->hctsiz_bm.xfer_size == 0) {
|
if (channel->hctsiz_bm.xfer_size == 0) {
|
||||||
pipe->pending_tx = false; // all data has been written
|
pipe->pending_tx = false; // all data has been written
|
||||||
|
Reference in New Issue
Block a user