From c07b2b0a07a25b6bdecaacef9ad229fbd5f3fd37 Mon Sep 17 00:00:00 2001 From: Wayne Lin Date: Mon, 15 Nov 2021 11:23:26 +0800 Subject: [PATCH] [Nuvoton] Update drivers. 1. ARM9 EHCI timeout issue. 2. Sync mainstream. --- .../libraries/n9h30/Driver/Source/nu_sdh.c | 19 ----- .../libraries/n9h30/UsbHostLib/src/ehci.c | 5 +- .../libraries/n9h30/rtt_port/drv_usbhost.c | 62 ++++++---------- .../libraries/nuc980/UsbHostLib/src/ehci.c | 7 +- .../libraries/nuc980/rtt_port/drv_usbhost.c | 74 ++++++++++++------- bsp/nuvoton/nk-980iot/board/nu_pin_init.c | 2 + 6 files changed, 78 insertions(+), 91 deletions(-) diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_sdh.c b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_sdh.c index aafd93a92d..5ebe2bdc78 100644 --- a/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_sdh.c +++ b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_sdh.c @@ -43,23 +43,6 @@ static uint8_t _SDH1_ucSDHCBuffer[512] __attribute__((aligned(32))); #endif -void dump_sdh_regs(SDH_T *sdh) -{ - rt_kprintf("\n+++++++++++++++++++++++\n"); - rt_kprintf(" %s\n", sdh->CTL & SDH_CTL_SDPORT_Msk ? "SD1" : "SD0"); - rt_kprintf(" DMACTL = 0x%08x\n", sdh->DMACTL); - rt_kprintf(" GCTL = 0x%08x\n", sdh->GCTL); - rt_kprintf(" GINTEN = 0x%08x\n", sdh->GINTEN); - rt_kprintf(" GINTSTS = 0x%08x\n", sdh->GINTSTS); - rt_kprintf(" CTL = 0x%08x\n", sdh->CTL); - rt_kprintf(" INTEN = 0x%08x\n", sdh->INTEN); - rt_kprintf(" INTSTS = 0x%08x\n", sdh->INTSTS); - rt_kprintf(" BLEN = 0x%08x\n", sdh->BLEN); - rt_kprintf(" TOUT = 0x%08x\n", sdh->TOUT); - rt_kprintf(" ECTL = 0x%08x\n", sdh->ECTL); - rt_kprintf("\n+++++++++++++++++++++++\n"); -} - void SDH_CheckRB(SDH_T *sdh) { while (1) @@ -405,8 +388,6 @@ uint32_t SDH_Init(SDH_T *sdh, SDH_INFO_T *pSD) pSD->R7Flag = 1ul; u32CmdTimeOut = 0xFFFFFul; - //dump_sdh_regs(sdh); - i = SDH_SDCmdAndRsp(sdh, pSD, 8ul, 0x00000155ul, u32CmdTimeOut); if (i == Successful) { diff --git a/bsp/nuvoton/libraries/n9h30/UsbHostLib/src/ehci.c b/bsp/nuvoton/libraries/n9h30/UsbHostLib/src/ehci.c index 28f5b890fd..dc20734d0e 100644 --- a/bsp/nuvoton/libraries/n9h30/UsbHostLib/src/ehci.c +++ b/bsp/nuvoton/libraries/n9h30/UsbHostLib/src/ehci.c @@ -907,7 +907,7 @@ static int visit_qtd(qTD_T *qtd) return 0; } -static void scan_asynchronous_list() +void scan_asynchronous_list() { QH_T *qh, *qh_tmp; qTD_T *q_pre, *qtd, *qtd_tmp; @@ -1096,9 +1096,8 @@ void iaad_remove_qh() //void EHCI_IRQHandler(void) void nu_ehci_isr(int vector, void *param) { - uint32_t intsts; + volatile uint32_t intsts = _ehci->USTSR; - intsts = _ehci->USTSR; _ehci->USTSR = intsts; /* clear interrupt status */ //USB_debug("ehci int_sts = 0x%x\n", intsts); diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_usbhost.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_usbhost.c index 128e40faa1..a5660ba328 100644 --- a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_usbhost.c +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_usbhost.c @@ -324,11 +324,7 @@ static rt_err_t nu_open_pipe(upipe_t pipe) { void *paddr = rt_malloc_align(512ul, CACHE_LINE_SIZE); RT_ASSERT(paddr != RT_NULL); -#if defined(BSP_USING_MMU) psPortDev->asPipePktBuf[pipe->pipe_index] = (void *)((uint32_t)paddr | NON_CACHE_MASK); -#else - psPortDev->asPipePktBuf[pipe->pipe_index] = paddr; -#endif } #endif @@ -380,9 +376,7 @@ static rt_err_t nu_close_pipe(upipe_t pipe) if (psPortDev->asPipePktBuf[pipe->pipe_index]) { void *paddr = psPortDev->asPipePktBuf[pipe->pipe_index]; -#if defined(BSP_USING_MMU) paddr = (void *)((uint32_t)paddr & ~NON_CACHE_MASK); -#endif rt_free_align(paddr); psPortDev->asPipePktBuf[pipe->pipe_index] = RT_NULL; } @@ -431,55 +425,41 @@ static int nu_bulk_xfer( UTR_T *psUTR, int timeouts) { + #define TIMEOUT_RETRY 3 -#define TIMEOUT_RETRY 10 - - UTR_T *psUTR_tmp = NULL; int retry = TIMEOUT_RETRY; - int ret; - int new_timeouts = timeouts / TIMEOUT_RETRY; - new_timeouts = (new_timeouts < 200) ? 200 : new_timeouts; - - psUTR_tmp = alloc_utr(psPortDev->pUDev); - if (!psUTR_tmp) + int ret = usbh_bulk_xfer(psUTR); + if (ret < 0) { - RT_DEBUG_LOG(RT_DEBUG_USB, ("nu_bulk_xfer ERROR: unable alloc UTR\n")); - return -1; + rt_kprintf("usbh_bulk_xfer %x\n", ret); + return ret; } - rt_memcpy((void *)psUTR_tmp, psUTR, sizeof(UTR_T)); - - while (retry > 0) + while ( retry > 0 ) { - ret = usbh_bulk_xfer(psUTR); - if (ret < 0) + if ( rt_completion_wait(&(psPortDev->utr_completion), timeouts) != 0 ) { - rt_kprintf("usbh_bulk_xfer %x\n", ret); - return ret; - } + rt_uint32_t level; - rt_thread_mdelay(1); + rt_kprintf("Request %d Timeout in %d ms!!\n", psUTR->data_len, timeouts); - //wait transfer done - if (rt_completion_wait(&(psPortDev->utr_completion), new_timeouts) == 0) - { - break; + rt_completion_init(&(psPortDev->utr_completion)); + rt_thread_mdelay(1); + + // Workaround: To fix timeout case, this way is traveling qh's linking-list again. + level = rt_hw_interrupt_disable(); + extern void scan_asynchronous_list(); + extern void iaad_remove_qh(); + scan_asynchronous_list(); + iaad_remove_qh(); + rt_hw_interrupt_enable(level); } else - { - // Timeout, let's retry. - retry--; - rt_kprintf("[%d/%d]Request Timeout in %d ms!! (bulk_xfer %d)\n", retry, TIMEOUT_RETRY, new_timeouts, psUTR->data_len); + break; - // Unlink - ret = usbh_quit_utr(psUTR); - rt_memcpy(psUTR, (void *)psUTR_tmp, sizeof(UTR_T)); - rt_completion_init(&(psPortDev->utr_completion)); - } + retry--; } - free_utr(psUTR_tmp); - return (retry > 0) ? 0 : -1; } diff --git a/bsp/nuvoton/libraries/nuc980/UsbHostLib/src/ehci.c b/bsp/nuvoton/libraries/nuc980/UsbHostLib/src/ehci.c index dbcda52196..dc20734d0e 100644 --- a/bsp/nuvoton/libraries/nuc980/UsbHostLib/src/ehci.c +++ b/bsp/nuvoton/libraries/nuc980/UsbHostLib/src/ehci.c @@ -297,6 +297,8 @@ static int ehci_init(void) _ehci->UCFGR = 0x1; /* enable port routing to EHCI */ _ehci->UIENR = HSUSBH_UIENR_USBIEN_Msk | HSUSBH_UIENR_UERRIEN_Msk | HSUSBH_UIENR_HSERREN_Msk | HSUSBH_UIENR_IAAEN_Msk; + _ehci->UASSTR = 0xfff; + usbh_delay_ms(1); /* delay 1 ms */ _ehci->UPSCR[0] = HSUSBH_UPSCR_PP_Msk; /* enable port 1 port power */ @@ -905,7 +907,7 @@ static int visit_qtd(qTD_T *qtd) return 0; } -static void scan_asynchronous_list() +void scan_asynchronous_list() { QH_T *qh, *qh_tmp; qTD_T *q_pre, *qtd, *qtd_tmp; @@ -1094,9 +1096,8 @@ void iaad_remove_qh() //void EHCI_IRQHandler(void) void nu_ehci_isr(int vector, void *param) { - uint32_t intsts; + volatile uint32_t intsts = _ehci->USTSR; - intsts = _ehci->USTSR; _ehci->USTSR = intsts; /* clear interrupt status */ //USB_debug("ehci int_sts = 0x%x\n", intsts); diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_usbhost.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_usbhost.c index a222acb461..a5660ba328 100644 --- a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_usbhost.c +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_usbhost.c @@ -181,12 +181,16 @@ static EP_INFO_T *GetFreePipe( if (i < NU_MAX_USBH_PIPE) { - EP_INFO_T *psEPInfo = rt_malloc(sizeof(EP_INFO_T)); + EP_INFO_T *psEPInfo = (EP_INFO_T *)rt_malloc_align(sizeof(EP_INFO_T), CACHE_LINE_SIZE); if (psEPInfo != RT_NULL) { +#if defined(BSP_USING_MMU) + psPortDev->apsEPInfo[i] = (EP_INFO_T *)((uint32_t)psEPInfo | NON_CACHE_MASK); +#else psPortDev->apsEPInfo[i] = psEPInfo; +#endif *pu8PipeIndex = i; - return psEPInfo; + return psPortDev->apsEPInfo[i]; } } } @@ -202,7 +206,11 @@ static void FreePipe( (u8PipeIndex < NU_MAX_USBH_PIPE) && (psPortDev->apsEPInfo[u8PipeIndex] != RT_NULL)) { - rt_free(psPortDev->apsEPInfo[u8PipeIndex]); + EP_INFO_T *psEPInfo = psPortDev->apsEPInfo[u8PipeIndex]; +#if defined(BSP_USING_MMU) + psEPInfo = (EP_INFO_T *)((uint32_t)psEPInfo & ~NON_CACHE_MASK); +#endif + rt_free_align(psEPInfo); psPortDev->apsEPInfo[u8PipeIndex] = RT_NULL; } } @@ -314,8 +322,9 @@ static rt_err_t nu_open_pipe(upipe_t pipe) #if defined(BSP_USING_MMU) if (!psPortDev->asPipePktBuf[pipe->pipe_index]) { - psPortDev->asPipePktBuf[pipe->pipe_index] = rt_malloc_align(512ul, CACHE_LINE_SIZE); - RT_ASSERT(psPortDev->asPipePktBuf[pipe->pipe_index] != RT_NULL); + void *paddr = rt_malloc_align(512ul, CACHE_LINE_SIZE); + RT_ASSERT(paddr != RT_NULL); + psPortDev->asPipePktBuf[pipe->pipe_index] = (void *)((uint32_t)paddr | NON_CACHE_MASK); } #endif @@ -366,7 +375,9 @@ static rt_err_t nu_close_pipe(upipe_t pipe) #if defined(BSP_USING_MMU) if (psPortDev->asPipePktBuf[pipe->pipe_index]) { - rt_free_align(psPortDev->asPipePktBuf[pipe->pipe_index]); + void *paddr = psPortDev->asPipePktBuf[pipe->pipe_index]; + paddr = (void *)((uint32_t)paddr & ~NON_CACHE_MASK); + rt_free_align(paddr); psPortDev->asPipePktBuf[pipe->pipe_index] = RT_NULL; } #endif @@ -414,26 +425,42 @@ static int nu_bulk_xfer( UTR_T *psUTR, int timeouts) { + #define TIMEOUT_RETRY 3 + + int retry = TIMEOUT_RETRY; int ret = usbh_bulk_xfer(psUTR); if (ret < 0) - return ret; - - //wait transfer done - if (rt_completion_wait(&(psPortDev->utr_completion), timeouts) < 0) { - rt_kprintf("Request Timeout in %d ms!! (bulk_xfer)\n", timeouts); - - rt_kprintf("psUTR->buff: %08x\n", psUTR->buff); - rt_kprintf("psUTR->data_len: %d\n", psUTR->data_len); - rt_kprintf("psUTR->xfer_len: %d\n", psUTR->xfer_len); - rt_kprintf("psUTR->ep: %08x\n", psUTR->ep); - rt_kprintf("psUTR->bIsTransferDone: %08x\n", psUTR->bIsTransferDone); - rt_kprintf("psUTR->status: %08x\n", psUTR->status); - rt_kprintf("psUTR->td_cnt: %08x\n", psUTR->td_cnt); - - return -1; + rt_kprintf("usbh_bulk_xfer %x\n", ret); + return ret; } - return 0; + + while ( retry > 0 ) + { + if ( rt_completion_wait(&(psPortDev->utr_completion), timeouts) != 0 ) + { + rt_uint32_t level; + + rt_kprintf("Request %d Timeout in %d ms!!\n", psUTR->data_len, timeouts); + + rt_completion_init(&(psPortDev->utr_completion)); + rt_thread_mdelay(1); + + // Workaround: To fix timeout case, this way is traveling qh's linking-list again. + level = rt_hw_interrupt_disable(); + extern void scan_asynchronous_list(); + extern void iaad_remove_qh(); + scan_asynchronous_list(); + iaad_remove_qh(); + rt_hw_interrupt_enable(level); + } + else + break; + + retry--; + } + + return (retry > 0) ? 0 : -1; } static int nu_int_xfer( @@ -525,7 +552,6 @@ static int nu_pipe_xfer(upipe_t pipe, rt_uint8_t token, void *buffer, int nbytes if ((pipe->ep.bEndpointAddress & USB_DIR_MASK) == USB_DIR_OUT) { rt_memcpy(buffer_nonch, buffer, nbytes); - mmu_clean_dcache((uint32_t)buffer_nonch, nbytes); } } #endif @@ -678,7 +704,6 @@ exit2_nu_pipe_xfer: { if ((pipe->ep.bEndpointAddress & USB_DIR_MASK) == USB_DIR_IN) { - mmu_invalidate_dcache((uint32_t)buffer_nonch, nbytes); rt_memcpy(buffer, buffer_nonch, nbytes); } } @@ -808,7 +833,6 @@ static rt_err_t nu_hcd_init(rt_device_t device) //install connect/disconnect callback usbh_install_conn_callback(nu_hcd_connect_callback, nu_hcd_disconnect_callback); - usbh_polling_root_hubs(); //create thread for polling usbh port status /* create usb hub thread */ diff --git a/bsp/nuvoton/nk-980iot/board/nu_pin_init.c b/bsp/nuvoton/nk-980iot/board/nu_pin_init.c index 002919896a..97ab099cfa 100644 --- a/bsp/nuvoton/nk-980iot/board/nu_pin_init.c +++ b/bsp/nuvoton/nk-980iot/board/nu_pin_init.c @@ -17,8 +17,10 @@ static void nu_pin_uart_init(void) /* UART0: GPF11, GPF12 */ outpw(REG_SYS_GPF_MFPH, (inpw(REG_SYS_GPF_MFPH) & 0xfff00fff) | 0x11000); +#if !defined(BOARD_USING_LCD_ILI9341) /* UART1: GPF9, GPF10 */ outpw(REG_SYS_GPF_MFPH, (inpw(REG_SYS_GPF_MFPH) & 0xfffff00f) | 0x00220); +#endif } static void nu_pin_emac_init(void)