add tuh_max3421e_int_api(), retry control if received NAK

This commit is contained in:
hathach 2023-08-24 16:27:32 +07:00
parent 3ed5d6c372
commit 344932d27e
No known key found for this signature in database
GPG Key ID: F5D50C6D51D17CBA
1 changed files with 40 additions and 20 deletions

View File

@ -28,6 +28,7 @@
#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
#include <stdatomic.h>
#include "host/hcd.h"
//--------------------------------------------------------------------+
@ -164,11 +165,15 @@ enum {
//--------------------------------------------------------------------+
typedef struct {
uint8_t xfer_type;
uint8_t data_toggle;
uint8_t xfer_complete;
uint16_t packet_size;
struct TU_ATTR_PACKED {
uint8_t is_iso : 1;
uint8_t data_toggle : 1;
uint8_t xfer_queued : 1;
uint8_t xfer_complete : 1;
};
uint16_t total_len;
uint16_t xferred_len;
uint8_t* buf;
@ -176,6 +181,7 @@ typedef struct {
typedef struct {
bool inited;
atomic_bool busy; // busy transferring
// cached register
uint8_t sndbc;
@ -198,8 +204,7 @@ static max2341_data_t _hcd_data;
void tuh_max3421_spi_cs_api(uint8_t rhport, bool active);
bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const * tx_buf, size_t tx_len, uint8_t * rx_buf, size_t rx_len);
//void tuh_max3421e_int_enable(uint8_t rhport, bool enabled);
void tuh_max3421e_int_api(uint8_t rhport, bool enabled);
//--------------------------------------------------------------------+
//
@ -348,6 +353,9 @@ tusb_speed_t handle_connect_irq(uint8_t rhport) {
bool hcd_init(uint8_t rhport) {
(void) rhport;
TU_LOG2_INT(sizeof(hcd_ep_t));
TU_LOG2_INT(sizeof(max2341_data_t));
tu_memclr(&_hcd_data, sizeof(_hcd_data));
// full duplex, interrupt negative edge
@ -382,12 +390,12 @@ bool hcd_init(uint8_t rhport) {
// Enable USB interrupt
void hcd_int_enable (uint8_t rhport) {
(void) rhport;
tuh_max3421e_int_api(rhport, true);
}
// Disable USB interrupt
void hcd_int_disable(uint8_t rhport) {
(void) rhport;
tuh_max3421e_int_api(rhport, false);
}
// Get frame number (1ms)
@ -447,17 +455,20 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) {
bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) {
(void) rhport;
(void) dev_addr;
(void) ep_desc;
uint8_t ep_num = tu_edpt_number(ep_desc->bEndpointAddress);
uint8_t ep_dir = tu_edpt_dir(ep_desc->bEndpointAddress);
_hcd_data.ep[ep_num][ep_dir].packet_size = tu_edpt_packet_size(ep_desc);
hcd_ep_t * ep = &_hcd_data.ep[ep_num][ep_dir];
ep->packet_size = tu_edpt_packet_size(ep_desc);
if (ep_desc->bEndpointAddress == 0) {
_hcd_data.ep[ep_num][1].packet_size = tu_edpt_packet_size(ep_desc);
_hcd_data.ep[0][1].packet_size = ep->packet_size;
}
ep->is_iso = (TUSB_XFER_ISOCHRONOUS == ep_desc->bmAttributes.xfer) ? 1 : 0;
return true;
}
@ -474,11 +485,13 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t daddr, uint8_t ep_addr, uint8_t * buf
ep->total_len = buflen;
ep->xferred_len = 0;
ep->xfer_complete = 0;
ep->xfer_queued = 1;
peraddr_write(daddr);
uint8_t hctl = 0;
uint8_t hxfr = ep_num;
if ( ep_num == 0 ) {
ep->data_toggle = 1;
if ( buffer == NULL || buflen == 0 ) {
@ -488,7 +501,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t daddr, uint8_t ep_addr, uint8_t * buf
hxfr_write(hxfr);
return true;
}
} else if ( ep->xfer_type == TUSB_XFER_ISOCHRONOUS ) {
} else if ( ep->is_iso ) {
hxfr |= HXFR_ISO;
}
@ -551,11 +564,13 @@ static void handle_xfer_done(uint8_t rhport) {
(void) rhport;
uint8_t const hrsl = reg_read(HRSL_ADDR);
uint8_t const result = hrsl & HRSL_RESULT_MASK;
uint8_t const hresult = hrsl & HRSL_RESULT_MASK;
uint8_t ep_num = _hcd_data.hxfr & HXFR_EPNUM_MASK;
xfer_result_t xfer_result;
TU_LOG3("HRSL: %02X\r\n", hrsl);
switch(result) {
//TU_LOG3("HRSL: %02X\r\n", hrsl);
switch(hresult) {
case HRSL_SUCCESS:
xfer_result = XFER_RESULT_SUCCESS;
break;
@ -568,21 +583,26 @@ static void handle_xfer_done(uint8_t rhport) {
// occurred when initialized without any pending transfer. Skip for now
return;
case HRSL_NAK:
// NAK on control, retry immediately
if (ep_num == 0) hxfr_write(_hcd_data.hxfr);
return;
default:
xfer_result = XFER_RESULT_FAILED;
break;
}
uint8_t ep_num = _hcd_data.hxfr & HXFR_EPNUM_MASK;
uint8_t const xfer_type = _hcd_data.hxfr & 0xf0;
uint8_t const hxfr_type = _hcd_data.hxfr & 0xf0;
if ( (xfer_type & HXFR_SETUP) || (xfer_type & HXFR_OUT_NIN) ) {
if ( (hxfr_type & HXFR_SETUP) || (hxfr_type & HXFR_OUT_NIN) ) {
// SETUP or OUT transfer
hcd_ep_t *ep = &_hcd_data.ep[ep_num][0];
uint8_t xact_len;
if (xfer_type & HXFR_SETUP) {
if ( hxfr_type & HXFR_SETUP) {
xact_len = 8;
} else if ( xfer_type & HXFR_HS ) {
} else if ( hxfr_type & HXFR_HS ) {
xact_len = 0;
} else {
xact_len = _hcd_data.sndbc;
@ -599,7 +619,7 @@ static void handle_xfer_done(uint8_t rhport) {
// IN transfer: fifo data is already received in RCVDAV IRQ
hcd_ep_t *ep = &_hcd_data.ep[ep_num][1];
if ( xfer_type & HXFR_HS ) {
if ( hxfr_type & HXFR_HS ) {
ep->xfer_complete = 1;
}