From 864d8381a7acbd89053b6d478c064872b4871ed9 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Sat, 26 Jun 2021 19:53:57 +0200 Subject: [PATCH 1/4] dcd_transmission xfer_fifo support. --- .../nxp/transdimension/dcd_transdimension.c | 114 +++++++++++++++++- 1 file changed, 112 insertions(+), 2 deletions(-) diff --git a/src/portable/nxp/transdimension/dcd_transdimension.c b/src/portable/nxp/transdimension/dcd_transdimension.c index 42047ef9..156695fc 100644 --- a/src/portable/nxp/transdimension/dcd_transdimension.c +++ b/src/portable/nxp/transdimension/dcd_transdimension.c @@ -128,7 +128,8 @@ typedef struct /// Due to the fact QHD is 64 bytes aligned but occupies only 48 bytes /// thus there are 16 bytes padding free that we can make use of. //--------------------------------------------------------------------+ - uint8_t reserved[16]; + tu_fifo_t * ff; + uint8_t reserved[12]; } dcd_qhd_t; TU_VERIFY_STATIC( sizeof(dcd_qhd_t) == 64, "size is not correct"); @@ -314,6 +315,39 @@ static void qtd_init(dcd_qtd_t* p_qtd, void * data_ptr, uint16_t total_bytes) } } +static void qtd_init_fifo(dcd_qtd_t* p_qtd, tu_fifo_buffer_info_t *info, uint16_t total_bytes) +{ + tu_memclr(p_qtd, sizeof(dcd_qtd_t)); + + p_qtd->next = QTD_NEXT_INVALID; + p_qtd->active = 1; + p_qtd->total_bytes = p_qtd->expected_bytes = total_bytes; + + // Fifo length has been trimmed to total_bytes + int16_t len_lin = info->len_lin; + + if (len_lin != 0) + { + p_qtd->buffer[0] = (uint32_t) info->ptr_lin; + + len_lin -= 4096 - ((uint32_t) info->ptr_lin - tu_align4k((uint32_t) info->ptr_lin)); + + // Set linear part + uint8_t i = 1; + for(; i<5; i++) + { + if (len_lin <= 0) break; + p_qtd->buffer[i] |= tu_align4k( p_qtd->buffer[i-1] ) + 4096; + len_lin -= 4096; + } + // Set wrapped part + for(uint8_t page = 0; i<5; i++, page++) + { + p_qtd->buffer[i] |= (uint32_t) info->ptr_wrap + 4096 * page; + } + } +} + //--------------------------------------------------------------------+ // DCD Endpoint Port //--------------------------------------------------------------------+ @@ -407,6 +441,67 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t return true; } +// fifo has to be aligned to 4k boundary +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +{ + dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs; + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + uint8_t const ep_idx = 2*epnum + dir; + + if ( epnum == 0 ) + { + // follows UM 24.10.8.1.1 Setup packet handling using setup lockout mechanism + // wait until ENDPTSETUPSTAT before priming data/status in response TODO add time out + while(dcd_reg->ENDPTSETUPSTAT & TU_BIT(0)) {} + } + + dcd_qhd_t * p_qhd = &_dcd_data.qhd[ep_idx]; + dcd_qtd_t * p_qtd = &_dcd_data.qtd[ep_idx]; + + tu_fifo_buffer_info_t fifo_info; + + if(dir == TUSB_DIR_IN) + { + tu_fifo_get_read_info(ff, &fifo_info); + } + else + { + tu_fifo_get_write_info(ff, &fifo_info); + } + + if(total_bytes <= fifo_info.len_lin) + { + // Limit transfer length to total_bytes + fifo_info.len_wrap = 0; + fifo_info.len_lin = total_bytes; + } + else + { + // Class driver ensure at least total_bytes elements in fifo + fifo_info.len_wrap = total_bytes - fifo_info.len_lin; + } + // Force the CPU to flush the buffer. We increase the size by 32 because the call aligns the + // address to 32-byte boundaries. + // void* cast to suppress cast-align warning, buffer must be + CleanInvalidateDCache_by_Addr((uint32_t*) tu_align((uint32_t) fifo_info.ptr_lin, 4), fifo_info.len_lin + 31); + if(fifo_info.len_wrap > 0) + CleanInvalidateDCache_by_Addr((uint32_t*) tu_align((uint32_t) fifo_info.ptr_wrap, 4), fifo_info.len_wrap + 31); + + //------------- Prepare qtd -------------// + qtd_init_fifo(p_qtd, &fifo_info, total_bytes); + p_qtd->int_on_complete = true; + p_qhd->qtd_overlay.next = (uint32_t) p_qtd; // link qtd to qhd + p_qhd->ff = ff; + + CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t)); + + // start transfer + dcd_reg->ENDPTPRIME = TU_BIT( ep_idx2bit(ep_idx) ) ; + + return true; +} + //--------------------------------------------------------------------+ // ISR //--------------------------------------------------------------------+ @@ -474,13 +569,28 @@ void dcd_int_handler(uint8_t rhport) if ( tu_bit_test(edpt_complete, ep_idx2bit(ep_idx)) ) { // 23.10.12.3 Failed QTD also get ENDPTCOMPLETE set + dcd_qhd_t * p_qhd = &_dcd_data.qhd[ep_idx]; dcd_qtd_t * p_qtd = &_dcd_data.qtd[ep_idx]; uint8_t result = p_qtd->halted ? XFER_RESULT_STALLED : ( p_qtd->xact_err ||p_qtd->buffer_err ) ? XFER_RESULT_FAILED : XFER_RESULT_SUCCESS; uint8_t const ep_addr = (ep_idx/2) | ( (ep_idx & 0x01) ? TUSB_DIR_IN_MASK : 0 ); - dcd_event_xfer_complete(rhport, ep_addr, p_qtd->expected_bytes - p_qtd->total_bytes, result, true); // only number of bytes in the IOC qtd + + uint16_t xferred_bytes = p_qtd->expected_bytes - p_qtd->total_bytes; + + if (p_qhd->ff) + { + if(tu_edpt_dir(ep_addr) == TUSB_DIR_IN) + { + tu_fifo_advance_read_pointer(p_qhd->ff, xferred_bytes); + } + else + { + tu_fifo_advance_write_pointer(p_qhd->ff, xferred_bytes); + } + } + dcd_event_xfer_complete(rhport, ep_addr, xferred_bytes, result, true); // only number of bytes in the IOC qtd } } } From 16b802d50cff6118952767b8fefa33dd0447ea91 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Sat, 26 Jun 2021 23:13:01 +0200 Subject: [PATCH 2/4] add dcd_edpt_close and iso xfer. --- .../nxp/transdimension/dcd_transdimension.c | 75 ++++++++++++------- 1 file changed, 49 insertions(+), 26 deletions(-) diff --git a/src/portable/nxp/transdimension/dcd_transdimension.c b/src/portable/nxp/transdimension/dcd_transdimension.c index 156695fc..a4d6c5d4 100644 --- a/src/portable/nxp/transdimension/dcd_transdimension.c +++ b/src/portable/nxp/transdimension/dcd_transdimension.c @@ -239,8 +239,9 @@ void dcd_init(uint8_t rhport) dcd_reg->USBMODE = USBMODE_CM_DEVICE; dcd_reg->OTGSC = OTGSC_VBUS_DISCHARGE | OTGSC_OTG_TERMINATION; - // TODO Force fullspeed on non-highspeed port - // dcd_reg->PORTSC1 = PORTSC1_FORCE_FULL_SPEED; +#if !TUD_OPT_HIGH_SPEED + dcd_reg->PORTSC1 = PORTSC1_FORCE_FULL_SPEED; +#endif CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t)); @@ -329,22 +330,22 @@ static void qtd_init_fifo(dcd_qtd_t* p_qtd, tu_fifo_buffer_info_t *info, uint16_ if (len_lin != 0) { p_qtd->buffer[0] = (uint32_t) info->ptr_lin; - + len_lin -= 4096 - ((uint32_t) info->ptr_lin - tu_align4k((uint32_t) info->ptr_lin)); - + // Set linear part uint8_t i = 1; for(; i<5; i++) { if (len_lin <= 0) break; p_qtd->buffer[i] |= tu_align4k( p_qtd->buffer[i-1] ) + 4096; - len_lin -= 4096; + len_lin -= 4096; } // Set wrapped part for(uint8_t page = 0; i<5; i++, page++) { p_qtd->buffer[i] |= (uint32_t) info->ptr_wrap + 4096 * page; - } + } } } @@ -373,9 +374,6 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) { - // TODO not support ISO yet - TU_VERIFY ( p_endpoint_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS); - uint8_t const epnum = tu_edpt_number(p_endpoint_desc->bEndpointAddress); uint8_t const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress); uint8_t const ep_idx = 2*epnum + dir; @@ -387,14 +385,25 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) dcd_qhd_t * p_qhd = &_dcd_data.qhd[ep_idx]; tu_memclr(p_qhd, sizeof(dcd_qhd_t)); - p_qhd->zero_length_termination = 1; p_qhd->max_package_size = p_endpoint_desc->wMaxPacketSize.size; p_qhd->qtd_overlay.next = QTD_NEXT_INVALID; + if (p_endpoint_desc->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS) + { + p_qhd->iso_mult = 1; + } else + { + p_qhd->zero_length_termination = 1; + } + CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t)); // Enable EP Control dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs; + + // Clear EP type + dcd_reg->ENDPTCTRL[epnum] &=~(0x03 << (dir ? 18 : 2)); + dcd_reg->ENDPTCTRL[epnum] |= ((p_endpoint_desc->bmAttributes.xfer << 2) | ENDPTCTRL_ENABLE | ENDPTCTRL_TOGGLE_RESET) << (dir ? 16 : 0); return true; @@ -406,6 +415,22 @@ void dcd_edpt_close_all (uint8_t rhport) // TODO implement dcd_edpt_close_all() } +void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs; + + // Flush EP + uint32_t flush_mask = TU_BIT(epnum) << (dir ? 16 : 0); + dcd_reg->ENDPTFLUSH = flush_mask; + while(dcd_reg->ENDPTFLUSH & flush_mask); + + // Clear EP enable + dcd_reg->ENDPTCTRL[epnum] &=~(ENDPTCTRL_ENABLE << (dir ? 16 : 0)); +} + bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs; @@ -442,7 +467,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t } // fifo has to be aligned to 4k boundary -bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs; uint8_t const epnum = tu_edpt_number(ep_addr); @@ -460,34 +485,33 @@ bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16 dcd_qtd_t * p_qtd = &_dcd_data.qtd[ep_idx]; tu_fifo_buffer_info_t fifo_info; - - if(dir == TUSB_DIR_IN) + + if (dir) { tu_fifo_get_read_info(ff, &fifo_info); - } - else + } else { tu_fifo_get_write_info(ff, &fifo_info); } - + if(total_bytes <= fifo_info.len_lin) { // Limit transfer length to total_bytes fifo_info.len_wrap = 0; fifo_info.len_lin = total_bytes; - } - else + } else { - // Class driver ensure at least total_bytes elements in fifo + // Class driver need to ensure at least total_bytes elements in fifo fifo_info.len_wrap = total_bytes - fifo_info.len_lin; } // Force the CPU to flush the buffer. We increase the size by 32 because the call aligns the // address to 32-byte boundaries. // void* cast to suppress cast-align warning, buffer must be CleanInvalidateDCache_by_Addr((uint32_t*) tu_align((uint32_t) fifo_info.ptr_lin, 4), fifo_info.len_lin + 31); - if(fifo_info.len_wrap > 0) + if (fifo_info.len_wrap > 0) + { CleanInvalidateDCache_by_Addr((uint32_t*) tu_align((uint32_t) fifo_info.ptr_wrap, 4), fifo_info.len_wrap + 31); - + } //------------- Prepare qtd -------------// qtd_init_fifo(p_qtd, &fifo_info, total_bytes); p_qtd->int_on_complete = true; @@ -576,20 +600,19 @@ void dcd_int_handler(uint8_t rhport) ( p_qtd->xact_err ||p_qtd->buffer_err ) ? XFER_RESULT_FAILED : XFER_RESULT_SUCCESS; uint8_t const ep_addr = (ep_idx/2) | ( (ep_idx & 0x01) ? TUSB_DIR_IN_MASK : 0 ); - + uint16_t xferred_bytes = p_qtd->expected_bytes - p_qtd->total_bytes; if (p_qhd->ff) { - if(tu_edpt_dir(ep_addr) == TUSB_DIR_IN) + if (tu_edpt_dir(ep_addr)) { tu_fifo_advance_read_pointer(p_qhd->ff, xferred_bytes); - } - else + } else { tu_fifo_advance_write_pointer(p_qhd->ff, xferred_bytes); } - } + } dcd_event_xfer_complete(rhport, ep_addr, xferred_bytes, result, true); // only number of bytes in the IOC qtd } } From 283783c082d2253984066cb475714217c63454d6 Mon Sep 17 00:00:00 2001 From: Mengsk Date: Thu, 9 Sep 2021 16:45:18 +0200 Subject: [PATCH 3/4] dcd_edpt_xfer_fifo: use qtd_init if restriction not met. --- .../nxp/transdimension/dcd_transdimension.c | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/portable/nxp/transdimension/dcd_transdimension.c b/src/portable/nxp/transdimension/dcd_transdimension.c index a4d6c5d4..0a18e711 100644 --- a/src/portable/nxp/transdimension/dcd_transdimension.c +++ b/src/portable/nxp/transdimension/dcd_transdimension.c @@ -494,7 +494,7 @@ bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16 tu_fifo_get_write_info(ff, &fifo_info); } - if(total_bytes <= fifo_info.len_lin) + if (total_bytes <= fifo_info.len_lin) { // Limit transfer length to total_bytes fifo_info.len_wrap = 0; @@ -508,12 +508,20 @@ bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16 // address to 32-byte boundaries. // void* cast to suppress cast-align warning, buffer must be CleanInvalidateDCache_by_Addr((uint32_t*) tu_align((uint32_t) fifo_info.ptr_lin, 4), fifo_info.len_lin + 31); - if (fifo_info.len_wrap > 0) - { - CleanInvalidateDCache_by_Addr((uint32_t*) tu_align((uint32_t) fifo_info.ptr_wrap, 4), fifo_info.len_wrap + 31); - } + //------------- Prepare qtd -------------// - qtd_init_fifo(p_qtd, &fifo_info, total_bytes); + + // In case of : wrapped part is present & buffer is aligned to 4k & buffer size is multiple of 4k + if (total_bytes > fifo_info.len_lin && (uint32_t)fifo_info.ptr_wrap == tu_align4k((uint32_t)fifo_info.ptr_wrap) && tu_fifo_depth(ff) == tu_align4k(tu_fifo_depth(ff))) + { + CleanInvalidateDCache_by_Addr((uint32_t*) tu_align((uint32_t) fifo_info.ptr_wrap, 4), fifo_info.len_wrap + 31); + qtd_init_fifo(p_qtd, &fifo_info, total_bytes); + } + else + { + qtd_init(p_qtd, fifo_info.ptr_lin, total_bytes); + } + p_qtd->int_on_complete = true; p_qhd->qtd_overlay.next = (uint32_t) p_qtd; // link qtd to qhd p_qhd->ff = ff; From 580893b3fe802d0aaeefa6c851dda828289c806c Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Fri, 10 Sep 2021 11:17:33 +0200 Subject: [PATCH 4/4] Shorter expr. --- src/portable/nxp/transdimension/dcd_transdimension.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/portable/nxp/transdimension/dcd_transdimension.c b/src/portable/nxp/transdimension/dcd_transdimension.c index 0a18e711..d669791d 100644 --- a/src/portable/nxp/transdimension/dcd_transdimension.c +++ b/src/portable/nxp/transdimension/dcd_transdimension.c @@ -512,7 +512,7 @@ bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16 //------------- Prepare qtd -------------// // In case of : wrapped part is present & buffer is aligned to 4k & buffer size is multiple of 4k - if (total_bytes > fifo_info.len_lin && (uint32_t)fifo_info.ptr_wrap == tu_align4k((uint32_t)fifo_info.ptr_wrap) && tu_fifo_depth(ff) == tu_align4k(tu_fifo_depth(ff))) + if (total_bytes > fifo_info.len_lin && !tu_offset4k((uint32_t)fifo_info.ptr_wrap) && !tu_offset4k(tu_fifo_depth(ff))) { CleanInvalidateDCache_by_Addr((uint32_t*) tu_align((uint32_t) fifo_info.ptr_wrap, 4), fifo_info.len_wrap + 31); qtd_init_fifo(p_qtd, &fifo_info, total_bytes);