nxp tdi: fix error td prevent further transfer

This commit is contained in:
hathach 2021-09-11 19:27:37 +07:00
parent ad8c0ee818
commit 1f7ade2b75
1 changed files with 31 additions and 23 deletions

View File

@ -91,12 +91,15 @@ typedef struct
uint32_t : 3 ; uint32_t : 3 ;
uint32_t int_on_complete : 1 ; uint32_t int_on_complete : 1 ;
volatile uint32_t total_bytes : 15 ; volatile uint32_t total_bytes : 15 ;
uint32_t : 0 ; uint32_t : 1 ;
// Word 2-6: Buffer Page Pointer List, Each element in the list is a 4K page aligned, physical memory address. The lower 12 bits in each pointer are reserved (except for the first one) as each memory pointer must reference the start of a 4K page // Word 2-6: Buffer Page Pointer List, Each element in the list is a 4K page aligned, physical memory address. The lower 12 bits in each pointer are reserved (except for the first one) as each memory pointer must reference the start of a 4K page
uint32_t buffer[5]; ///< buffer1 has frame_n for TODO Isochronous uint32_t buffer[5]; ///< buffer1 has frame_n for TODO Isochronous
//------------- DCD Area -------------// //--------------------------------------------------------------------+
// TD is 32 bytes aligned but occupies only 28 bytes
// Therefore there are 4 bytes padding that we can use.
//--------------------------------------------------------------------+
uint16_t expected_bytes; uint16_t expected_bytes;
uint8_t reserved[2]; uint8_t reserved[2];
} dcd_qtd_t; } dcd_qtd_t;
@ -109,11 +112,10 @@ typedef struct
// Word 0: Capabilities and Characteristics // Word 0: Capabilities and Characteristics
uint32_t : 15 ; ///< Number of packets executed per transaction descriptor 00 - Execute N transactions as demonstrated by the USB variable length protocol where N is computed using Max_packet_length and the Total_bytes field in the dTD. 01 - Execute one transaction 10 - Execute two transactions 11 - Execute three transactions Remark: Non-isochronous endpoints must set MULT = 00. Remark: Isochronous endpoints must set MULT = 01, 10, or 11 as needed. uint32_t : 15 ; ///< Number of packets executed per transaction descriptor 00 - Execute N transactions as demonstrated by the USB variable length protocol where N is computed using Max_packet_length and the Total_bytes field in the dTD. 01 - Execute one transaction 10 - Execute two transactions 11 - Execute three transactions Remark: Non-isochronous endpoints must set MULT = 00. Remark: Isochronous endpoints must set MULT = 01, 10, or 11 as needed.
uint32_t int_on_setup : 1 ; ///< Interrupt on setup This bit is used on control type endpoints to indicate if USBINT is set in response to a setup being received. uint32_t int_on_setup : 1 ; ///< Interrupt on setup This bit is used on control type endpoints to indicate if USBINT is set in response to a setup being received.
uint32_t max_package_size : 11 ; ///< This directly corresponds to the maximum packet size of the associated endpoint (wMaxPacketSize) uint32_t max_packet_size : 11 ; ///< Endpoint's wMaxPacketSize
uint32_t : 2 ; uint32_t : 2 ;
uint32_t zero_length_termination : 1 ; ///< This bit is used for non-isochronous endpoints to indicate when a zero-length packet is received to terminate transfers in case the total transfer length is “multiple”. 0 - Enable zero-length packet to terminate transfers equal to a multiple of Max_packet_length (default). 1 - Disable zero-length packet on transfers that are equal in length to a multiple Max_packet_length. uint32_t zero_length_termination : 1 ; ///< This bit is used for non-isochronous endpoints to indicate when a zero-length packet is received to terminate transfers in case the total transfer length is “multiple”. 0 - Enable zero-length packet to terminate transfers equal to a multiple of Max_packet_length (default). 1 - Disable zero-length packet on transfers that are equal in length to a multiple Max_packet_length.
uint32_t iso_mult : 2 ; ///< uint32_t iso_mult : 2 ; ///<
uint32_t : 0 ;
// Word 1: Current qTD Pointer // Word 1: Current qTD Pointer
volatile uint32_t qtd_addr; volatile uint32_t qtd_addr;
@ -125,8 +127,8 @@ typedef struct
volatile tusb_control_request_t setup_request; volatile tusb_control_request_t setup_request;
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
/// Due to the fact QHD is 64 bytes aligned but occupies only 48 bytes // QHD is 64 bytes aligned but occupies only 48 bytes
/// thus there are 16 bytes padding free that we can make use of. // Therefore there are 16 bytes padding that we can use.
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
uint8_t reserved[16]; uint8_t reserved[16];
} dcd_qhd_t; } dcd_qhd_t;
@ -214,7 +216,7 @@ static void bus_reset(uint8_t rhport)
//------------- Set up Control Endpoints (0 OUT, 1 IN) -------------// //------------- Set up Control Endpoints (0 OUT, 1 IN) -------------//
_dcd_data.qhd[0][0].zero_length_termination = _dcd_data.qhd[0][1].zero_length_termination = 1; _dcd_data.qhd[0][0].zero_length_termination = _dcd_data.qhd[0][1].zero_length_termination = 1;
_dcd_data.qhd[0][0].max_package_size = _dcd_data.qhd[0][1].max_package_size = CFG_TUD_ENDPOINT0_SIZE; _dcd_data.qhd[0][0].max_packet_size = _dcd_data.qhd[0][1].max_packet_size = CFG_TUD_ENDPOINT0_SIZE;
_dcd_data.qhd[0][0].qtd_overlay.next = _dcd_data.qhd[0][1].qtd_overlay.next = QTD_NEXT_INVALID; _dcd_data.qhd[0][0].qtd_overlay.next = _dcd_data.qhd[0][1].qtd_overlay.next = QTD_NEXT_INVALID;
_dcd_data.qhd[0][0].int_on_setup = 1; // OUT only _dcd_data.qhd[0][0].int_on_setup = 1; // OUT only
@ -348,7 +350,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc)
tu_memclr(p_qhd, sizeof(dcd_qhd_t)); tu_memclr(p_qhd, sizeof(dcd_qhd_t));
p_qhd->zero_length_termination = 1; p_qhd->zero_length_termination = 1;
p_qhd->max_package_size = p_endpoint_desc->wMaxPacketSize.size; p_qhd->max_packet_size = p_endpoint_desc->wMaxPacketSize.size;
p_qhd->qtd_overlay.next = QTD_NEXT_INVALID; p_qhd->qtd_overlay.next = QTD_NEXT_INVALID;
CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t)); CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t));
@ -390,7 +392,9 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t
//------------- Prepare qtd -------------// //------------- Prepare qtd -------------//
qtd_init(p_qtd, buffer, total_bytes); qtd_init(p_qtd, buffer, total_bytes);
p_qtd->int_on_complete = true; p_qtd->int_on_complete = true;
p_qhd->qtd_overlay.next = (uint32_t) p_qtd; // link qtd to qhd
p_qhd->qtd_overlay.halted = false; // clear any previous error
p_qhd->qtd_overlay.next = (uint32_t) p_qtd; // activate by linking qtd to qhd
CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t)); CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t));
@ -404,15 +408,22 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t
// ISR // ISR
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
static void process_edpt_complete_isr(uint8_t rhport, uint8_t ep_num, uint8_t dir) static void process_edpt_complete_isr(uint8_t rhport, uint8_t epnum, uint8_t dir)
{ {
dcd_qtd_t * p_qtd = &_dcd_data.qtd[ep_num][dir]; dcd_qtd_t * p_qtd = &_dcd_data.qtd[epnum][dir];
uint8_t result = p_qtd->halted ? XFER_RESULT_STALLED : uint8_t result = p_qtd->halted ? XFER_RESULT_STALLED :
( p_qtd->xact_err || p_qtd->buffer_err ) ? XFER_RESULT_FAILED : XFER_RESULT_SUCCESS; ( p_qtd->xact_err || p_qtd->buffer_err ) ? XFER_RESULT_FAILED : XFER_RESULT_SUCCESS;
if ( result != XFER_RESULT_SUCCESS )
{
dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs;
// flush to abort error buffer
dcd_reg->ENDPTFLUSH = TU_BIT(epnum + (dir ? 16 : 0));
}
// only number of bytes in the IOC qtd // only number of bytes in the IOC qtd
dcd_event_xfer_complete(rhport, tu_edpt_addr(ep_num, dir), p_qtd->expected_bytes - p_qtd->total_bytes, result, true); dcd_event_xfer_complete(rhport, tu_edpt_addr(epnum, dir), p_qtd->expected_bytes - p_qtd->total_bytes, result, true);
} }
void dcd_int_handler(uint8_t rhport) void dcd_int_handler(uint8_t rhport)
@ -473,11 +484,11 @@ void dcd_int_handler(uint8_t rhport)
} }
} }
if (int_status & INTR_USB)
{
// Make sure we read the latest version of _dcd_data. // Make sure we read the latest version of _dcd_data.
CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t)); CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t));
if (int_status & INTR_USB)
{
uint32_t const edpt_complete = dcd_reg->ENDPTCOMPLETE; uint32_t const edpt_complete = dcd_reg->ENDPTCOMPLETE;
dcd_reg->ENDPTCOMPLETE = edpt_complete; // acknowledge dcd_reg->ENDPTCOMPLETE = edpt_complete; // acknowledge
@ -491,18 +502,15 @@ void dcd_int_handler(uint8_t rhport)
} }
// 23.10.12.3 Failed QTD also get ENDPTCOMPLETE set // 23.10.12.3 Failed QTD also get ENDPTCOMPLETE set
if (int_status & INTR_ERROR) // nothing to do, we will submit xfer as error to usbd
{ // if (int_status & INTR_ERROR) { }
TU_LOG_HEX(1, int_status);
TU_LOG_HEX(1, edpt_complete);
}
if ( edpt_complete ) if ( edpt_complete )
{ {
for(uint8_t ep_num = 0; ep_num < DCD_ATTR_ENDPOINT_MAX; ep_num++) for(uint8_t epnum = 0; epnum < DCD_ATTR_ENDPOINT_MAX; epnum++)
{ {
if ( tu_bit_test(edpt_complete, ep_num) ) process_edpt_complete_isr(rhport, ep_num, TUSB_DIR_OUT); if ( tu_bit_test(edpt_complete, epnum) ) process_edpt_complete_isr(rhport, epnum, TUSB_DIR_OUT);
if ( tu_bit_test(edpt_complete, ep_num+16) ) process_edpt_complete_isr(rhport, ep_num, TUSB_DIR_IN); if ( tu_bit_test(edpt_complete, epnum+16) ) process_edpt_complete_isr(rhport, epnum, TUSB_DIR_IN);
} }
} }
} }