/** * @file hv_drv_Uart.c * @brief uart driver layer file. * * @author HiView SoC Software Team * @version 1.0.0 * @date 2023-06-14 * @copyright Copyright(c),2023-6, Hiview Software. All rights reserved. * */ #include "hv_vos_Comm.h" #include "hv_cal_Dma.h" #include "hv_chip_Config.h" #include "hv_comm_Define.h" #include "hv_drv_Uart.h" #include "hv_comm_Assert.h" #define UART_LCR_MASK 0xE0 #define UART_PARITY_MASK 0x03 #define UART_PARITY_EVEN_MASK 0x18 #define UART_PARITY_ODD_MASK 0x08 #define UART_PARITY_NONE_MASK 0x00 #define UART_DATALEN_MASK 0x03 #define UART_STOP_POS 2U #define UART_STOP_MASK (0x01UL << UART_STOP_POS) /*!< Received Data Available */ #define UART_RECV_INT_EN 0x01 /*!< Transmit Holding Register Empty Interrupt */ #define UART_TRANEMPTY_INT_EN 0x02 /*!< Receiver Line Status Interrupt */ #define UART_RECVSTATUS_INT_EN 0x04 /*!< Modem Status */ #define UART_MODEMSTATUS_INT_EN 0x08 #define UART_FIFO_MASK 0x06 /* Interrupt Type */ #define UART_INT_MODEM_STATUS 0x00 #define UART_INT_NO_INTERRUPT_PENDING 0x01 #define UART_INT_THR_EMPTY 0x02 #define UART_INT_RECEIVED_DATA_AVAILABLE 0x04 #define UART_INT_RECEIVER_LINE_STATUS 0x06 #define UART_INT_BUSY_DETECT 0x07 #define UART_INT_CHARACTER_TIMEOUT 0x0c struct _UartSelf { UartInitParam stInitParam; UINT32 uiBaseOffset; /*!< Pointer to UART Tx transfer Buffer */ const UCHAR8 *pucTxBuffPtr; /*!< UART Tx Transfer size */ USHORT16 usTxXferSize; /*!< UART Tx Transfer Counter */ USHORT16 usTxXferCount; /*!< Pointer to UART Rx transfer Buffer */ UCHAR8 *pucRxBuffPtr; /*!< UART Rx Transfer size */ USHORT16 usRxXferSize; /*!< UART Rx Transfer Counter */ USHORT16 usRxXferCount; /*!< UART Tx DMA Handle parameters */ DmaSelf *pstHdmaTx; /*!< UART Rx DMA Handle parameters */ DmaSelf *pstHdmaRx; /*!< UART communication state */ UartStateType enState; /*!< UART Error code */ UINT32 errorCode; /*!< UART Binary Semaphore */ HV_VOS_SEMAPHORE_S* pstUartBinarySema; }; static UartSelf s_astUart[UART_PORT_MAX]; #define UART_BUFF_SIZE 32 static UCHAR8 g_aucUartRxBuf[UART_BUFF_SIZE] = {0}; static UCHAR8 g_ucUartBufIndex = 0; static Status Uart_IntReceive(UartSelf *pstSelf) { UINT32 uiValue = 0; rs_cpu_sys_uart0_dlh_ier ier = {0}; uiValue = HV_R32(pstSelf->uiBaseOffset + CPU_SYS_UART0_LSR); uiValue = cpu_sys_uart0_lsr(uiValue)->reg_DR; while (uiValue & 0x1) { uiValue = HV_R32(pstSelf->uiBaseOffset + CPU_SYS_UART0_THR_DLL); if (pstSelf->stInitParam.bNewInterface == HV_TRUE) { g_aucUartRxBuf[(g_ucUartBufIndex++)%UART_BUFF_SIZE] = uiValue; } else { *pstSelf->pucRxBuffPtr++ = (UCHAR8)uiValue; if (--pstSelf->usRxXferCount == 0) { uiValue = HV_R32(pstSelf->uiBaseOffset + CPU_SYS_UART0_DLH_IER); /* Disable Received Data Available Interrupt */ ier.reg_DLH_IER = cpu_sys_uart0_dlh_ier(uiValue)->reg_DLH_IER & ~UART_RECV_INT_EN; HV_W32_REG(pstSelf->uiBaseOffset + CPU_SYS_UART0_DLH_IER, ier); if (pstSelf->enState == UART_STATE_BUSY_TX_RX) { pstSelf->enState = UART_STATE_BUSY_TX; } else { pstSelf->enState = UART_STATE_READY; } if (pstSelf->stInitParam.fCallback) { pstSelf->stInitParam.fCallback(UART_INT_RX_COMPLETE, pstSelf->stInitParam.pCallbackArg, 0); } return HV_SUCCESS; } } uiValue = HV_R32(pstSelf->uiBaseOffset + CPU_SYS_UART0_LSR); uiValue = cpu_sys_uart0_lsr(uiValue)->reg_DR; } if (pstSelf->stInitParam.bNewInterface == HV_TRUE) { pstSelf->stInitParam.fCallback(UART_INT_RX_COMPLETE, g_aucUartRxBuf, g_ucUartBufIndex); g_ucUartBufIndex = 0; } return HV_SUCCESS; } static Status Uart_IntTransmit(UartSelf *pstSelf) { UINT32 uiValue = 0; rs_cpu_sys_uart0_dlh_ier ier = {0}; if (pstSelf->usTxXferCount == 0) { uiValue = HV_R32(pstSelf->uiBaseOffset + CPU_SYS_UART0_DLH_IER); /* Disable Transmit Holding Register Empty Interrupt */ ier.reg_DLH_IER = cpu_sys_uart0_dlh_ier(uiValue)->reg_DLH_IER & ~UART_TRANEMPTY_INT_EN; HV_W32_REG(pstSelf->uiBaseOffset + CPU_SYS_UART0_DLH_IER, ier); if (pstSelf->enState == UART_STATE_BUSY_TX_RX) { pstSelf->enState = UART_STATE_BUSY_RX; } else { pstSelf->enState = UART_STATE_READY; } if (pstSelf->stInitParam.fCallback) { pstSelf->stInitParam.fCallback(UART_INT_TX_COMPLETE, pstSelf->stInitParam.pCallbackArg, 0); } return HV_SUCCESS; } do { HV_W32(pstSelf->uiBaseOffset + CPU_SYS_UART0_THR_DLL, *pstSelf->pucTxBuffPtr); pstSelf->pucTxBuffPtr += 1; if (--pstSelf->usTxXferCount == 0) { return HV_SUCCESS; } uiValue = HV_R32(pstSelf->uiBaseOffset + CPU_SYS_UART0_USR); uiValue = cpu_sys_uart0_usr(uiValue)->reg_TFNF; } while (pstSelf->stInitParam.bFifoEnable && (uiValue & 0x1)); return HV_SUCCESS; } static Status Uart_DmaRxCpltCallback(DmaSelf* pstArg) { UartSelf *pstSelf = (UartSelf *)Hv_Cal_Dma_GetParent(pstArg); if (pstSelf->enState == UART_STATE_BUSY_TX_RX) { pstSelf->enState = UART_STATE_BUSY_TX; } else { pstSelf->enState = UART_STATE_READY; } if (pstSelf->stInitParam.fCallback) { pstSelf->stInitParam.fCallback(UART_DMA_RX_COMPLETE, pstSelf->stInitParam.pCallbackArg, 0); } return HV_SUCCESS; } static Status Uart_DmaTxCpltCallback(DmaSelf* pstArg) { UartSelf *pstSelf = (UartSelf *)Hv_Cal_Dma_GetParent(pstArg); if (pstSelf->enState == UART_STATE_BUSY_TX_RX) { pstSelf->enState = UART_STATE_BUSY_RX; } else { pstSelf->enState = UART_STATE_READY; } if (pstSelf->stInitParam.fCallback) { pstSelf->stInitParam.fCallback(UART_DMA_TX_COMPLETE, pstSelf->stInitParam.pCallbackArg, 0); } return HV_SUCCESS; } static HV_VOS_ISR_RESULT_E Uart_IrqHandler(UINT32 uiIrqNum, void *pArg) { UartSelf *pstSelf = (UartSelf *)pArg; UINT32 uiValue = 0; HV_UNUSED(uiIrqNum); uiValue = HV_R32(pstSelf->uiBaseOffset + CPU_SYS_UART0_FCR); switch (uiValue & 0xf) { case UART_INT_MODEM_STATUS: { break; } case UART_INT_NO_INTERRUPT_PENDING: { break; } case UART_INT_THR_EMPTY: { Uart_IntTransmit(pstSelf); break; } case UART_INT_RECEIVED_DATA_AVAILABLE: { Uart_IntReceive(pstSelf); Hv_Vos_ReleaseSemaphoreFromISR(pstSelf->pstUartBinarySema); break; } case UART_INT_RECEIVER_LINE_STATUS: { pstSelf->errorCode = UART_ERROR_NONE; uiValue = HV_R32(pstSelf->uiBaseOffset + CPU_SYS_UART0_LSR); if (cpu_sys_uart0_lsr(uiValue)->reg_BI & 0x1) { pstSelf->errorCode |= UART_ERROR_BI; } if (cpu_sys_uart0_lsr(uiValue)->reg_FE & 0x1) { pstSelf->errorCode |= UART_ERROR_FE; } if (cpu_sys_uart0_lsr(uiValue)->reg_PE & 0x1) { pstSelf->errorCode |= UART_ERROR_PE; } if (cpu_sys_uart0_lsr(uiValue)->reg_OE & 0x1) { pstSelf->errorCode |= UART_ERROR_ORE; } if (cpu_sys_uart0_lsr(uiValue)->reg_RFE & 0x1) { pstSelf->errorCode |= UART_ERROR_RFE; } //HV_LOGI("error errorCode = 0x%x\n", pstSelf->errorCode); break; } case UART_INT_BUSY_DETECT: { //HV_LOGI("busy detect\n"); uiValue = HV_R32(pstSelf->uiBaseOffset + CPU_SYS_UART0_USR); HV_UNUSED(uiValue); break; } case UART_INT_CHARACTER_TIMEOUT: { //HV_LOGI("character timeout\n"); break; } default: { break; } } return HV_VOS_ISR_HANDLED; } void Hv_Drv_Uart_SetDmaTx(UartSelf *pstSelf, DmaSelf *pstHdmaTx) { pstSelf->pstHdmaTx = pstHdmaTx; Hv_Cal_Dma_SetParent(pstHdmaTx,(void*)pstSelf); Hv_Cal_Dma_SetDstAddr(pstHdmaTx,CPU_SYS_UART0_THR_DLL + pstSelf->uiBaseOffset); return; } void Hv_Drv_Uart_SetDmaRx(UartSelf *pstSelf, DmaSelf *pstHdmaRx) { pstSelf->pstHdmaRx = pstHdmaRx; Hv_Cal_Dma_SetParent(pstHdmaRx,(void*)pstSelf); Hv_Cal_Dma_SetSrcAddr(pstHdmaRx,CPU_SYS_UART0_THR_DLL + pstSelf->uiBaseOffset); return; } /** Initialize uart * @param initParam pointer to uart configure parameters * @return uart structure pointer */ UartSelf *Hv_Drv_Uart_Init(UartInitParam *pstInitParam) { rs_cpu_sys_uart0_fcr fcr = {0}; rs_cpu_sys_uart0_lcr_ext lcr_ext = {0}; UartSelf *pstSelf; UINT32 uiIrqNum = 0; HV_ASSERT_TRUE_RET(pstInitParam != NULL,NULL); HV_ASSERT_PEEK_TRUE(pstInitParam->enPort < UART_PORT_MAX); pstSelf = &s_astUart[pstInitParam->enPort]; HV_MEMCPY(&s_astUart[pstInitParam->enPort], pstInitParam, sizeof(UartInitParam)); if (pstInitParam->enPort == UART_PORT_0) { pstSelf->uiBaseOffset = 0; uiIrqNum = HV_CHIP_IRQ_UART0; } else if (pstInitParam->enPort == UART_PORT_1) { pstSelf->uiBaseOffset = HV_UART1_BASE_ADDRESS - HV_UART0_BASE_ADDRESS; uiIrqNum = HV_CHIP_IRQ_UART1; } else { } if (pstInitParam->bFifoEnable) { fcr.reg_FIFOE = 1; fcr.reg_RFIFOR = 1; fcr.reg_XFIFOR = 1; fcr.TET = pstInitParam->enTxFiFoTrig; fcr.RT = pstInitParam->enRxFiFoTrig; } if (pstInitParam->b9BitMode) { lcr_ext.reg_DLS_E = 1; lcr_ext.reg_ADDR_MATCH = 0; lcr_ext.reg_SEND_ADDR = 0; lcr_ext.reg_TRANSMIT_MODE = 1; HV_W32_REG(pstSelf->uiBaseOffset + CPU_SYS_UART0_LCR_EXT, lcr_ext); } if (pstInitParam->bNewInterface) { if (pstInitParam->fCallback == NULL) { HV_LOGE("no callback regisstered\n"); } } HV_W32_REG(pstSelf->uiBaseOffset + CPU_SYS_UART0_FCR, fcr); Hv_Drv_Uart_SetBaudrate(pstSelf, pstInitParam->uiBaudrate); Hv_Drv_Uart_SetFormat(pstSelf, pstInitParam->enParity, pstInitParam->enStopbit, pstInitParam->enWordlen); HV_W32(pstSelf->uiBaseOffset + CPU_SYS_UART0_DLH_IER, UART_RECVSTATUS_INT_EN | UART_MODEMSTATUS_INT_EN); Hv_Vos_AttachIsr(uiIrqNum, Uart_IrqHandler, pstSelf); //Hv_Vos_SetIrqPrio(uiIrqNum,pstInitParam->uiPriority); Hv_Vos_UnmaskIrq(uiIrqNum); Hv_Vos_ConfigIrq(uiIrqNum, HV_TRUE, 0); pstSelf->errorCode = UART_ERROR_NONE; pstSelf->enState = UART_STATE_READY; pstSelf->pstUartBinarySema = Hv_Vos_InitSemaphore(1, 0); return pstSelf; } /** brief De-initialize uart * @param self uart pointer */ void Hv_Drv_Uart_Cleanup(UartSelf *pstSelf) { HV_ASSERT(pstSelf->stInitParam.enPort < UART_PORT_MAX); Hv_Drv_Uart_CleanFifo(pstSelf); if (pstSelf->stInitParam.enPort == UART_PORT_0) { Hv_Vos_ConfigIrq(HV_CHIP_IRQ_UART0, HV_FALSE, 0); Hv_Vos_MaskIrq(HV_CHIP_IRQ_UART0); Hv_Vos_DetachIsr(HV_CHIP_IRQ_UART0, Uart_IrqHandler); } else if (pstSelf->stInitParam.enPort == UART_PORT_1) { Hv_Vos_ConfigIrq(HV_CHIP_IRQ_UART1, HV_FALSE, 0); Hv_Vos_MaskIrq(HV_CHIP_IRQ_UART1); Hv_Vos_DetachIsr(HV_CHIP_IRQ_UART1, Uart_IrqHandler); } else { } pstSelf->stInitParam.fCallback = NULL; pstSelf->stInitParam.pCallbackArg = NULL; pstSelf->enState = UART_STATE_RESET; return; } /** brief De-initialize uart * @param self uart pointer */ void Hv_Drv_Uart_CleanFifo(UartSelf *pstSelf) { UINT32 uiValue = 0; uiValue = HV_R32(pstSelf->uiBaseOffset + CPU_SYS_UART0_FCR); HV_W32(pstSelf->uiBaseOffset + CPU_SYS_UART0_FCR, uiValue | UART_FIFO_MASK); return; } /** Detection puiBaudrate of uart * @param enPort uart enPort * @param puiBaudrate detection puiBaudrate value * @return result */ Status Hv_Drv_Uart_BaudrateDetection(UartPortIndex enPort, UINT32 *puiBaudrate) { UINT32 uiValue = 0; UINT32 uiBaseOffset = 0; HV_ASSERT(enPort < UART_PORT_MAX); if (enPort == UART_PORT_0) { uiBaseOffset = 0; } else if (enPort == UART_PORT_1) { uiBaseOffset = HV_UART1_BASE_ADDRESS - HV_UART0_BASE_ADDRESS; } else { } /* auto baud rate enable */ HV_W32_FIELD_EX(CPU_SYS_UART0_UART_CTL0, uiBaseOffset, reg_abr_en, 1); while(1) { uiValue = HV_R32(uiBaseOffset + CPU_SYS_UART0_UART_CTL0); if (cpu_sys_uart0_uart_ctl0(uiValue)->reg_abrf == 1 && cpu_sys_uart0_uart_ctl0(uiValue)->reg_bit_num != 0) { *puiBaudrate = HV_CHIP_CLK_APB / cpu_sys_uart0_uart_ctl0(uiValue)->reg_bit_num; HV_LOGI("get Baudrate = %d\n", *puiBaudrate); break; } } /* auto baud rate disable */ HV_W32_FIELD_EX(CPU_SYS_UART0_UART_CTL0, uiBaseOffset, reg_abr_en, 0); return HV_SUCCESS; } /** Set baudrate of uart * @param self uart pointer * @param baudrate baudrate * @return result */ Status Hv_Drv_Uart_SetBaudrate(UartSelf *pstSelf, UINT32 uiBaudrate) { UINT32 uiDivider = 0; FLOAT32 fBrd = 0; fBrd = (HV_CHIP_CLK_APB >> 4) / (FLOAT32)uiBaudrate + 1 / 2; uiDivider = (UINT32)fBrd; /* Enable setup uiBaudrate */ HV_W32_FIELD_EX(CPU_SYS_UART0_LCR, pstSelf->uiBaseOffset, reg_DLAB, 1); HV_W32_FIELD_EX(CPU_SYS_UART0_THR_DLL, pstSelf->uiBaseOffset, reg_THR_DLL, uiDivider & 0xff); HV_W32_FIELD_EX(CPU_SYS_UART0_DLH_IER, pstSelf->uiBaseOffset, reg_DLH_IER, (uiDivider >> 8) & 0xff); /* Disable setup uiBaudrate */ HV_W32_FIELD_EX(CPU_SYS_UART0_LCR, pstSelf->uiBaseOffset, reg_DLAB, 0); return HV_SUCCESS; } /** Set serial format of homebus * @param self uart pointer * @param parity parity * @param stopbit stop bit * @param wordlen word length * @return result */ Status Hv_Drv_Uart_SetFormat(UartSelf *pstSelf, UartParity enParity, UartStopBit enStopbit, UartWordLen enWordlen) { UINT32 uiData = 0; UINT32 uiValue = 0; pstSelf->stInitParam.enParity = enParity; pstSelf->stInitParam.enStopbit = enStopbit; pstSelf->stInitParam.enWordlen = enWordlen; uiData = (((pstSelf->stInitParam.enStopbit << UART_STOP_POS) & UART_STOP_MASK) | (pstSelf->stInitParam.enWordlen & UART_DATALEN_MASK)); uiValue = HV_R32(pstSelf->uiBaseOffset + CPU_SYS_UART0_LCR); switch (pstSelf->stInitParam.enParity & UART_PARITY_MASK) { case UART_PARITY_EVEN: { uiValue = (uiValue & UART_LCR_MASK) | UART_PARITY_EVEN_MASK | uiData; break; } case UART_PARITY_ODD: { uiValue = (uiValue & UART_LCR_MASK) | UART_PARITY_ODD_MASK | uiData; break; } default: { uiValue = (uiValue & UART_LCR_MASK) | UART_PARITY_NONE_MASK | uiData; break; } } HV_W32(pstSelf->uiBaseOffset + CPU_SYS_UART0_LCR, uiValue); return HV_SUCCESS; } /** Receives an amount of data in polling mode * @param self uart pointer * @param data pointer to data buffer * @param size amount of data to be received * @param timeout timeout duration ms * @return result */ Status Hv_Drv_Uart_Receive(UartSelf *pstSelf, UCHAR8 *pucData, USHORT16 usSize, UINT32 uiTimeout) { UINT32 uiValue = 0; UINT64 ulStartTick = 0; if (pucData == NULL || usSize == 0) { return HV_INVALID; } if (pstSelf->enState == UART_STATE_READY || pstSelf->enState == UART_STATE_BUSY_TX) { if (pstSelf->enState == UART_STATE_BUSY_TX) { pstSelf->enState = UART_STATE_BUSY_TX_RX; } else { pstSelf->enState = UART_STATE_BUSY_RX; } pstSelf->usRxXferSize = usSize; pstSelf->usRxXferCount = usSize; ulStartTick = Hv_Vos_GetTick(); while (pstSelf->usRxXferCount > 0) { uiValue = HV_R32(pstSelf->uiBaseOffset + CPU_SYS_UART0_LSR); uiValue = cpu_sys_uart0_lsr(uiValue)->reg_DR; if (uiValue == 1) { pstSelf->usRxXferCount--; uiValue = HV_R32(pstSelf->uiBaseOffset + CPU_SYS_UART0_THR_DLL); *pucData++ = (UCHAR8)uiValue; } else { if (uiTimeout != 0 && Hv_Vos_GetTick() - ulStartTick >= uiTimeout) { if (pstSelf->enState == UART_STATE_BUSY_TX_RX) { pstSelf->enState = UART_STATE_BUSY_TX; } else { pstSelf->enState = UART_STATE_READY; } HV_LOGE("Receive timeout!\n"); return HV_FAILURE; } } } if (pstSelf->enState == UART_STATE_BUSY_TX_RX) { pstSelf->enState = UART_STATE_BUSY_TX; } else { pstSelf->enState = UART_STATE_READY; } return HV_SUCCESS; } else { return HV_FAILURE; } } /** enable uart receive int�� * @param ucPort uart port * @return result */ Status Hv_Drv_Uart_EnableReceive(UCHAR8 ucPort) { UINT32 uiValue = 0; rs_cpu_sys_uart0_dlh_ier ier = {0}; UartSelf *pstSelf = &s_astUart[ucPort]; if (pstSelf == NULL) { HV_LOGE("port not inited\n"); return HV_FAILURE; } uiValue = HV_R32(pstSelf->uiBaseOffset + CPU_SYS_UART0_DLH_IER); /* Enable Received Data Available Interrupt */ ier.reg_DLH_IER = cpu_sys_uart0_dlh_ier(uiValue)->reg_DLH_IER | UART_RECV_INT_EN; HV_W32_REG(pstSelf->uiBaseOffset + CPU_SYS_UART0_DLH_IER, ier); return HV_SUCCESS; } /** Receives an amount of data in non blocking mode * @param self uart pointer * @param data pointer to data buffer * @param size amount of data to be received * @return result */ Status Hv_Drv_Uart_IntReceive(UartSelf *pstSelf, UCHAR8 *pucData, USHORT16 usSize) { UINT32 uiValue = 0; rs_cpu_sys_uart0_dlh_ier ier = {0}; if (pucData == NULL || usSize == 0) { return HV_INVALID; } if (pstSelf->enState == UART_STATE_READY || pstSelf->enState == UART_STATE_BUSY_TX) { if (pstSelf->enState == UART_STATE_BUSY_TX) { pstSelf->enState = UART_STATE_BUSY_TX_RX; } else { pstSelf->enState = UART_STATE_BUSY_RX; } pstSelf->pucRxBuffPtr = pucData; pstSelf->usRxXferSize = usSize; pstSelf->usRxXferCount = usSize; uiValue = HV_R32(pstSelf->uiBaseOffset + CPU_SYS_UART0_DLH_IER); /* Enable Received Data Available Interrupt */ ier.reg_DLH_IER = cpu_sys_uart0_dlh_ier(uiValue)->reg_DLH_IER | UART_RECV_INT_EN; HV_W32_REG(pstSelf->uiBaseOffset + CPU_SYS_UART0_DLH_IER, ier); return HV_SUCCESS; } else { return HV_FAILURE; } } /** Receives an amount of data in blocking mode * @param self uart pointer * @param data pointer to data buffer * @param size amount of data to be received * @return result */ Status Hv_Drv_Uart_BlockReceive(UartSelf *pstSelf, UCHAR8 *pucData, USHORT16 usSize) { while (1) { /* Due to UART_RECV_INT_EN is set in Hv_Drv_Uart_IntReceive, so must run it before P operation.*/ if (Hv_Drv_Uart_IntReceive(pstSelf, pucData, usSize) == HV_SUCCESS) { break; } else { /* P operation */ Hv_Vos_AcquireSemaphore(pstSelf->pstUartBinarySema); } } return HV_SUCCESS; } /** Receives an amount of data in non blocking mode * @param self uart pointer * @param data pointer to data buffer * @param size amount of data to be received * @return result */ Status Hv_Drv_Uart_DmaReceive(UartSelf *pstSelf, UCHAR8 *pucData, USHORT16 usSize) { if (pucData == NULL || usSize == 0) { return HV_INVALID; } if (pstSelf->enState == UART_STATE_READY || pstSelf->enState == UART_STATE_BUSY_TX) { if (pstSelf->enState == UART_STATE_BUSY_TX) { pstSelf->enState = UART_STATE_BUSY_TX_RX; } else { pstSelf->enState = UART_STATE_BUSY_RX; } pstSelf->pucRxBuffPtr = pucData; pstSelf->usRxXferSize = usSize; pstSelf->usRxXferCount = usSize; Hv_Cal_Dma_XferCallbackBond(pstSelf->pstHdmaRx, Uart_DmaRxCpltCallback); Hv_Cal_Dma_SetBlockSize(pstSelf->pstHdmaRx, usSize); Hv_Cal_Dma_SetDstAddr(pstSelf->pstHdmaRx, (UINT32)pucData); Hv_Cal_Dma_ChannelEn(pstSelf->pstHdmaRx); return HV_SUCCESS; } else { return HV_FAILURE; } } /** Get character by UART * @param self uart pointer * @param data pointer to data buffer * @return result */ Status Hv_Drv_Uart_GetChar(UartSelf *pstSelf, UCHAR8 *pucData) { UINT32 uiValue = 0; if (pstSelf->enState == UART_STATE_READY || pstSelf->enState == UART_STATE_BUSY_TX) { if (pstSelf->enState == UART_STATE_BUSY_TX) { pstSelf->enState = UART_STATE_BUSY_TX_RX; } else { pstSelf->enState = UART_STATE_BUSY_RX; } do { uiValue = HV_R32(pstSelf->uiBaseOffset + CPU_SYS_UART0_LSR); uiValue = cpu_sys_uart0_lsr(uiValue)->reg_DR; }while(uiValue == 0); uiValue = HV_R32(pstSelf->uiBaseOffset + CPU_SYS_UART0_THR_DLL); *pucData = (UCHAR8)uiValue; if (pstSelf->enState == UART_STATE_BUSY_TX_RX) { pstSelf->enState = UART_STATE_BUSY_TX; } else { pstSelf->enState = UART_STATE_READY; } return HV_SUCCESS; } else { return HV_FAILURE; } } /** Output address by UART with 9bit mode * @param self uart pointer * @param data device address * @return result */ Status Hv_Drv_Uart_PutAddr(UartSelf *pstSelf, UCHAR8 ucAddr) { UINT32 uiValue = 0; if (pstSelf->enState == UART_STATE_READY || pstSelf->enState == UART_STATE_BUSY_RX) { if (pstSelf->enState == UART_STATE_BUSY_RX) { pstSelf->enState = UART_STATE_BUSY_TX_RX; } else { pstSelf->enState = UART_STATE_BUSY_TX; } do { uiValue = HV_R32(pstSelf->uiBaseOffset + CPU_SYS_UART0_LSR); uiValue = cpu_sys_uart0_lsr(uiValue)->reg_THRE; } while(uiValue == 0); uiValue = (1 << 8) | ucAddr; HV_W32(pstSelf->uiBaseOffset + CPU_SYS_UART0_THR_DLL, uiValue); if (pstSelf->enState == UART_STATE_BUSY_TX_RX) { pstSelf->enState = UART_STATE_BUSY_RX; } else { pstSelf->enState = UART_STATE_READY; } return HV_SUCCESS; } else { return HV_FAILURE; } } /** Output character by UART * @param self uart pointer * @param data outputed character * @return result */ Status Hv_Drv_Uart_PutChar(UartSelf *pstSelf, UCHAR8 ucData) { UINT32 uiValue = 0; if (pstSelf->enState == UART_STATE_READY || pstSelf->enState == UART_STATE_BUSY_RX) { if (pstSelf->enState == UART_STATE_BUSY_RX) { pstSelf->enState = UART_STATE_BUSY_TX_RX; } else { pstSelf->enState = UART_STATE_BUSY_TX; } do { uiValue = HV_R32(pstSelf->uiBaseOffset + CPU_SYS_UART0_LSR); uiValue = cpu_sys_uart0_lsr(uiValue)->reg_THRE; } while(uiValue == 0); HV_W32(pstSelf->uiBaseOffset + CPU_SYS_UART0_THR_DLL, ucData); if (pstSelf->enState == UART_STATE_BUSY_TX_RX) { pstSelf->enState = UART_STATE_BUSY_RX; } else { pstSelf->enState = UART_STATE_READY; } return HV_SUCCESS; } else { return HV_FAILURE; } } /** Sends an amount of data in blocking mode * @param self uart pointer * @param data pointer to data buffer * @param size amount of data to be sent * @param timeout timeout duration ms * @return result */ Status Hv_Drv_Uart_Transmit(UartSelf *pstSelf, const UCHAR8 *pucData, USHORT16 usSize, UINT32 uiTimeout) { UINT32 uiValue = 0; UINT64 ulStartTick = 0; if (pucData == NULL || usSize == 0) { return HV_INVALID; } if (pstSelf->enState == UART_STATE_READY || pstSelf->enState == UART_STATE_BUSY_RX) { if (pstSelf->enState == UART_STATE_BUSY_RX) { pstSelf->enState = UART_STATE_BUSY_TX_RX; } else { pstSelf->enState = UART_STATE_BUSY_TX; } pstSelf->usTxXferSize = usSize; pstSelf->usTxXferCount = usSize; ulStartTick = Hv_Vos_GetTick(); while (pstSelf->usTxXferCount > 0) { uiValue = HV_R32(pstSelf->uiBaseOffset + CPU_SYS_UART0_LSR); uiValue = cpu_sys_uart0_lsr(uiValue)->reg_THRE; if (uiValue == 1) { pstSelf->usTxXferCount--; HV_W32(pstSelf->uiBaseOffset + CPU_SYS_UART0_THR_DLL, *pucData); pucData += 1; } else { if (uiTimeout != 0 && Hv_Vos_GetTick() - ulStartTick >= uiTimeout) { if (pstSelf->enState == UART_STATE_BUSY_TX_RX) { pstSelf->enState = UART_STATE_BUSY_RX; } else { pstSelf->enState = UART_STATE_READY; } HV_LOGE("Transmit timeout!\n"); return HV_FAILURE; } } } if (pstSelf->enState == UART_STATE_BUSY_TX_RX) { pstSelf->enState = UART_STATE_BUSY_RX; } else { pstSelf->enState = UART_STATE_READY; } return HV_SUCCESS; } else { return HV_FAILURE; } } /** Sends an amount of data * @param ucPort uart port * @param data pointer to data buffer * @param size amount of data to be sent * @return result */ Status Hv_Drv_Uart_Send(UCHAR8 ucPort, const UCHAR8 *pucData, USHORT16 usSize) { UINT32 uiValue = 0; UartSelf *pstSelf = &s_astUart[ucPort]; if (pstSelf == NULL) { HV_LOGE("port not inited\n"); return HV_FAILURE; } rs_cpu_sys_uart0_dlh_ier ier = {0}; if (pucData == NULL || usSize == 0) { return HV_INVALID; } if (pstSelf->enState == UART_STATE_READY || pstSelf->enState == UART_STATE_BUSY_RX) { if (pstSelf->enState == UART_STATE_BUSY_RX) { pstSelf->enState = UART_STATE_BUSY_TX_RX; } else { pstSelf->enState = UART_STATE_BUSY_TX; } pstSelf->pucTxBuffPtr = pucData; pstSelf->usTxXferSize = usSize; pstSelf->usTxXferCount = usSize; uiValue = HV_R32(pstSelf->uiBaseOffset + CPU_SYS_UART0_DLH_IER); /* Enable Transmit Holding Register Empty Interrupt */ ier.reg_DLH_IER = cpu_sys_uart0_dlh_ier(uiValue)->reg_DLH_IER | UART_TRANEMPTY_INT_EN; HV_W32_REG(pstSelf->uiBaseOffset + CPU_SYS_UART0_DLH_IER, ier); return HV_SUCCESS; } else { return HV_FAILURE; } } /** Sends an amount of data in non blocking mode * @param self uart pointer * @param data pointer to data buffer * @param size amount of data to be sent * @return result */ Status Hv_Drv_Uart_IntTransmit(UartSelf *pstSelf, const UCHAR8 *pucData, USHORT16 usSize) { UINT32 uiValue = 0; rs_cpu_sys_uart0_dlh_ier ier = {0}; if (pucData == NULL || usSize == 0) { return HV_INVALID; } if (pstSelf->enState == UART_STATE_READY || pstSelf->enState == UART_STATE_BUSY_RX) { if (pstSelf->enState == UART_STATE_BUSY_RX) { pstSelf->enState = UART_STATE_BUSY_TX_RX; } else { pstSelf->enState = UART_STATE_BUSY_TX; } pstSelf->pucTxBuffPtr = pucData; pstSelf->usTxXferSize = usSize; pstSelf->usTxXferCount = usSize; uiValue = HV_R32(pstSelf->uiBaseOffset + CPU_SYS_UART0_DLH_IER); /* Enable Transmit Holding Register Empty Interrupt */ ier.reg_DLH_IER = cpu_sys_uart0_dlh_ier(uiValue)->reg_DLH_IER | UART_TRANEMPTY_INT_EN; HV_W32_REG(pstSelf->uiBaseOffset + CPU_SYS_UART0_DLH_IER, ier); return HV_SUCCESS; } else { return HV_FAILURE; } } /** Sends an amount of data in non blocking mode * @param self uart pointer * @param data pointer to data buffer * @param size amount of data to be sent * @return result */ Status Hv_Drv_Uart_DmaTransmit(UartSelf *pstSelf, const UCHAR8 *pucData, USHORT16 usSize) { if (pucData == NULL || usSize == 0) { return HV_INVALID; } if (pstSelf->enState == UART_STATE_READY || pstSelf->enState == UART_STATE_BUSY_RX) { if (pstSelf->enState == UART_STATE_BUSY_RX) { pstSelf->enState = UART_STATE_BUSY_TX_RX; } else { pstSelf->enState = UART_STATE_BUSY_TX; } pstSelf->pucTxBuffPtr = pucData; pstSelf->usTxXferSize = usSize; pstSelf->usTxXferCount = usSize; Hv_Cal_Dma_XferCallbackBond(pstSelf->pstHdmaTx, Uart_DmaTxCpltCallback); Hv_Cal_Dma_SetBlockSize(pstSelf->pstHdmaTx, usSize); Hv_Cal_Dma_SetSrcAddr(pstSelf->pstHdmaTx, (UINT32)pucData); Hv_Cal_Dma_ChannelEn(pstSelf->pstHdmaTx); return HV_SUCCESS; } else { return HV_FAILURE; } } /** Get errorCode of uart * @param self uart pointer * @return errorCode result */ UINT32 Hv_Drv_Uart_GetErrorCode(UartSelf *pstSelf) { HV_LOGI("error errorCode = 0x%x\n", pstSelf->errorCode); return pstSelf->errorCode; } /** Get empty of uart * @param self uart pointer * @return result empty or not */ BOOL Hv_Drv_Uart_IsEmpty(UartSelf *pstSelf) { rs_cpu_sys_uart0_lsr lsr = {0}; HV_R32_REG(pstSelf->uiBaseOffset + CPU_SYS_UART0_LSR, lsr); return !lsr.reg_DR; } /** * @brief uart enable for log. * @param[in] bEnble: on/off */ VOID Hv_Drv_EnableUart(BOOL bEnble) { HV_LOGI("EnableUart %d",bEnble); /* uart0_tx swtich */ if (bEnble) { HV_W32_FIELD(RX_SH08_TOP_RX_CTRL_4, reg_uart0_tx_func_sel , 1); //HV_W32_FIELD(RX_SH08_TOP_RX_CTRL_4, reg_uart0_rx_func_sel , 1); //HV_W32_FIELD(RX_SH08_TOP_RX_CTRL_8, reg_uart0_sin_in_sel , 0); } else { HV_W32_FIELD(RX_SH08_TOP_RX_CTRL_4, reg_uart0_tx_func_sel , 0); //HV_W32_FIELD(RX_SH08_TOP_RX_CTRL_4, reg_uart0_rx_func_sel , 0); //HV_W32_FIELD(RX_SH08_TOP_RX_CTRL_8, reg_uart0_sin_in_sel , 2; } return; }