draft MAX3421E NAK retry handling next frame

This commit is contained in:
IngHK 2024-03-26 08:10:32 +01:00
parent 0cb7204e60
commit 9fdb1c1684
1 changed files with 44 additions and 1 deletions

View File

@ -28,6 +28,8 @@
#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
#define NAK_RETRY_HANDLING 1
#include <stdatomic.h>
#include "host/hcd.h"
@ -180,6 +182,9 @@ typedef struct {
uint8_t data_toggle : 1;
uint8_t xfer_pending : 1;
uint8_t xfer_complete : 1;
#if NAK_RETRY_HANDLING
uint8_t retry_pending : 1;
#endif
};
struct TU_ATTR_PACKED {
@ -593,7 +598,7 @@ void xact_out(uint8_t rhport, max3421_ep_t *ep, bool switch_ep, bool in_isr) {
}
uint8_t const xact_len = (uint8_t) tu_min16(ep->total_len - ep->xferred_len, ep->packet_size);
TU_ASSERT(_hcd_data.hirq & HIRQ_SNDBAV_IRQ,);
// TU_ASSERT(_hcd_data.hirq & HIRQ_SNDBAV_IRQ,);
if (xact_len) {
fifo_write(rhport, SNDFIFO_ADDR, ep->buf, xact_len, in_isr);
}
@ -803,6 +808,7 @@ static void handle_xfer_done(uint8_t rhport, bool in_isr) {
xfer_result_t xfer_result;
switch(hresult) {
case HRSL_SUCCESS:
// putchar('S');
xfer_result = XFER_RESULT_SUCCESS;
break;
@ -811,6 +817,19 @@ static void handle_xfer_done(uint8_t rhport, bool in_isr) {
break;
case HRSL_NAK:
// putchar('N');
#if NAK_RETRY_HANDLING
ep->retry_pending = 1;
ep->xfer_pending = 0;
max3421_ep_t * next_ep = find_next_pending_ep(ep);
if (next_ep) {
// switch to next pending TODO could have issue with double buffered if not clear previously out data
xact_inout(rhport, next_ep, true, in_isr);
} else {
// no more pending
atomic_flag_clear(&_hcd_data.busy);
}
#else
if (ep_num == 0) {
// NAK on control, retry immediately
hxfr_write(rhport, _hcd_data.hxfr, in_isr);
@ -828,6 +847,7 @@ static void handle_xfer_done(uint8_t rhport, bool in_isr) {
TU_ASSERT(false,);
}
}
#endif
return;
case HRSL_BAD_REQ:
@ -909,6 +929,29 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) {
if (hirq & HIRQ_FRAME_IRQ) {
_hcd_data.frame_count++;
#if NAK_RETRY_HANDLING
// retry EPs
max3421_ep_t * next_ep = NULL;
for (size_t i = 0; i < CFG_TUH_MAX3421_ENDPOINT_TOTAL; i++) {
max3421_ep_t * ep = &_hcd_data.ep[i];
// set retryable EPs to pending
if (ep->retry_pending) {
// putchar('R');
ep->xfer_pending = 1;
ep->retry_pending = 0;
if (next_ep == NULL) {
next_ep = &_hcd_data.ep[i];
}
}
}
// trigger 1st retryable EP
if (next_ep) {
if ( !atomic_flag_test_and_set(&_hcd_data.busy) ) {
xact_inout(rhport, next_ep, true, in_isr);
}
}
#endif
}
if (hirq & HIRQ_CONDET_IRQ) {